XBMC Übergabe des aktuellen Videos von einem XBMC zum nächsten

Begonnen von siggi85, 20 Juni 2014, 18:50:21

Vorheriges Thema - Nächstes Thema

siggi85

Hallo,

ich nutze XBMC mit einer zentralen Datenbank, welche mit SMB Freigaben aller Dateien gefüllt ist. Ist es irgendwie möglich mithilfe das aktuellen XBMC Moduls, das Video was aktuell auf XBMC1 abgespielt wird zu beenden und dann von der gleichen Stelle auf XBMC2 abzuspielen? Mit "open" kann man den Pfad aus dem Reading "currentMedia" laden, jedoch startet die Wiedergabe von Anfang.

Ziel ist es, wenn man zBim Wohnzimmer schaut und im Schlafzimmer weitergucken möchte, einen Knopf (Tasker Shortcut) zu drücken und dann geht automatisch die XBMC Instanz im Schlafzimmer an und das Video was aktuell im Wohnzimmer läuft wartet im Pause Modus an der gleichen Stelle schon im Schlafzimmer. Zusätzlich kann über diesen Automatismus natürlich die XBMC Instanz im Wohnzimmer auch gleich herunter gefahren werden. :)
Das Hauptproblem was ich momentan sehe ist das Starten an der gleichen Stelle... Das Time Reading kann ich nach einer Pause zwar ablesen aber nicht auf der zweiten XBMC Instanz setzen...

justme1968

ich weiß... ganz schlimm offtopic... aber schau die mal plex statt xbmc an. da gibt es nur eine zentrale db auf einem server und alle clients sind immer aynchron. du kannst auf einem ahfören und auf einem beliebigen anderen weiter schauen. falls du sowieso einen zentralen server betreibst ist es mit plex sehr viel einfacher.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

P.A.Trick

Also laut API sollte das gehen!

http://wiki.xbmc.org/?title=JSON-RPC_API/v6#Player.Seek

Na mal sehen ob sich jemand überwindet das in das Modul einzubauen :D
Cubietruck,RPI,QNAP Ts-419p+, FS20, FRITZ!DECT200, 7 MAX! Thermostate, 3 MAX! Fensterkontakte, Kodi, CUL V3.3, EM1000S, LW12, LD382, HUE, HM-CFG-USB-2, 1x HM-LC-SW1-FM, 2x HM-LC-SW2-FM, 2x HM-LC-Sw1PBU-FM, 3xHM-LC-Bl1PBU-FM,HM-SEC-RHS, 2xHM-SEC-SD,HM-WDS30-T-O, 3x HM-LC-Dim1TPBU-FM, RPI+AddOn

siggi85

Also normalerweise funktioniert das in XBMC auch von da an weiter zu schauen. Aber ich benötige diese Funktion halt über einen Automatismus. Der "open" Befehl öffnet ja nur den kompletten Link. Man bräuchte einen "db_open" oder so um einen Datenbankeintrag abspielen zu können in dem dann der aktuelle Spielstatus gespeichert ist. Am besten mit einer Option:
set <device> db_open Die\ Simpsons/Season1/Episode1 beginning|state

Wenn man den Player auf einen bestimmten Zeitwert setzen könnte wie es P.A.Trick vorgeschlagen hat, dann kann man sich das halt selber zusammen basteln in dem man vorher den Zeitwert aus dem Time Reading von XBMC1 liest und auf XBMC2 setzt sobald das Video gestartet ist.

Vielleicht findet sich ja jemand der etwas in der Art implementiert... *liebguck* :)

vbs

Ich hab mal vor einiger Zeit ein XBMC Script geschrieben, das auf Knopfdruck den zuletzt gespielten Track/Film fortsetzt: http://forum.xbmc.org/showthread.php?tid=109310
Das speichert jedoch die Position in einer Datei lokal in addon_data. Wäre jedoch theoretisch möglich das Script über mehrere Geräte hinweg zu nutzen, wenn du den Pfad zu addon_data auch zentral auf deinem Server ablegst: http://wiki.xbmc.org/index.php?title=MySQL/Sync_other_parts_of_XBMC
Dann müsstest du es noch hinbekommen, das Script über fhem zu starten. Weiss nicht, ob das geht.

siggi85

Das mit dem Script wäre eine Idee. Aber eine nativere Lösung über das FHEM Modul wäre sicher der elegantere Weg.

Ich habe gerade entdeckt, dass die "Player.Open" Funktion das starten eines Datenbankeintrages UND die Resumefunktion unterstützt!

[...]
  "description": "Start playback of either the playlist with the given ID, a slideshow with the pictures from the given directory or a single file or an item from the database.",
[...]
        "resume": {
          "type": [
            {
              "description": "Whether to resume from the resume point or not",
              "type": "boolean"
            },
[...]


Player.Open

siggi85

#6
Ok, das sollte für einen richtigen Programmierer (also jemand anderes als ich  ;) ) nicht die Schwierigkeit sein. Ich habe die 70_XBMC.pm m folgendermaßen angepasst:

In der XBMC_Set Subroutine folgende Zeilen hinzugefügt:
  elsif($cmd eq 'openmovieid') {
    return XBMC_Set_Open($hash, 'movie', @args);
  }


In der XBMC_Set_Open Subroutine:
elsif($opt eq 'movie') {
    $params = {
      'item' => {
        'movieid' => $path
      }
    };
  }


Im res Skalar openmovieid hinzugefügt:
  "open opendir openmovieid shuffle:toggle,on,off repeat:one,all,off volumeUp:noArg volumeDown:noArg " .

Im HTML Teil ganz unten:
  <li><b>openmovieid &lt;path&gt;</b> -  Plays the content of the movieid</li>


Wenn ich in der XBMC_Set_Open Subroutine eine feste ID eintrage funktioniert das direkte Aufrufen eines Films in der Datenbank über die ID.
set xbmc_device openmovieid 123

Ich bekomme aber die Weitergabe der Zahl von FHEM aus nicht hin. Wohlmöglich weil die path Variable für Pathangaben genutzt wird und die Zahl unterwegs verfälscht wird. Wäre super wenn sich das jemand anschauen könnte. Falls jemand das gleich implementiert würde ich darum bitten auf diesem Wege gleich episodeid, musicvideoid und songid einzupflegen (es gibt noch genreid, albumid und artistid, für mich erstmal uninteressant, aber ggf. wegen der Vollständigkeit implementieren).
Ggf. wäre auch eine elegantere Lösung besser (siehe unten). Dann wären auch genreid etc. nicht störend.

set <device> openid movie|episode|musicvid|song <integer> resume|start

EDIT: Die Resumefunktion die es im "Player.Open" gibt habe ich programmiertechnisch nicht beachtet, nur in meinem Wunschfunktionsaufruf über FHEM.

vbs

Könntest du mal deine aktuelle komplette Datei mit dran hängen?

siggi85

Zitat von: vbs am 24 Juni 2014, 09:21:09
Könntest du mal deine aktuelle komplette Datei mit dran hängen?

Na klar, mache ich sobald ich heute abend zu Hause bin! Danke dass du dich der Sache annimmst. :)

siggi85

Diese in dieser Datei sind alle Änderungen für episodeid und movieid. Die Path Variable in Zeile 677 und 683 wird nur leider nicht richtig übernommen und funktioniert nur wenn ich die jeweilige ID direkt in den Code schreibe.

vbs

Alles fast gut, nur ein kleiner Schönheitsfehler: In deiner Version sieht der JSON-String so aus:
{"params":{"item":{"movieid":"81"}},"jsonrpc":"2.0","method":"Player.Open"}

Also die movieid wird als String übertragen (böse).
Wenn du den Code nimmst:
  } elsif($opt eq 'movieid') {
    $params = {
      'item' => {
        'movieid' => $path + 0
      }
    };
  } elsif($opt eq 'episodeid') {
    $params = {
      'item' => {
        'episodeid' => $path + 0
      }
    };
  }

Man beachte das "+0", dann sieht der JSON-String so aus:
{"params":{"item":{"movieid":81}},"jsonrpc":"2.0","method":"Player.Open"}

Und damit gehts dann schon :)
Vielleicht kennt jemand noch einen schöneren Weg als das "+0", um aus nem String eine Zahl zu machen...

siggi85

Achso, also waren es nur die " die gestört haben.  ::) Danke für die Hilfe!
Ich bin am überlegen ob man gleich den "Resume" Parameter im Modul standardmäßig mit auf "true" setzt. Falls ein Film keinen gespeicherten Savepunkt besitzt, sollte er ja trotzdem von Anfang starten. Müsste man aber testen.
Schöner wäre es, wenn man sich die Resume Verhaltensweise beim Aufruf des Films über eine Option aussuchen kann, aber ich weiß leider nicht wie ich dies als zusätzliche Option im Aufruf mit einbauen könnte?!

vbs

Als normaler Parameter für open wäre natürlich möglich. Optionaler Parameter hinten dran sollte zB bei openmovieid ja kein Problem sein. Bei dem normalen open wird es jedoch schwieriger, da der angegebene Pfad IIRC Leerzeichen enthalten darf. Der Parameter müsste dann also weiter vorne als Pflichtparameter stehen.
Alternativ könnte man ein Attribut anlegen (zB useResume), das angibt, ob bei open-Befehl resumet werden soll oder nicht.

siggi85

Zitat von: vbs am 25 Juni 2014, 16:01:55
Als normaler Parameter für open wäre natürlich möglich. Optionaler Parameter hinten dran sollte zB bei openmovieid ja kein Problem sein. Bei dem normalen open wird es jedoch schwieriger, da der angegebene Pfad IIRC Leerzeichen enthalten darf. Der Parameter müsste dann also weiter vorne als Pflichtparameter stehen.
Alternativ könnte man ein Attribut anlegen (zB useResume), das angibt, ob bei open-Befehl resumet werden soll oder nicht.

Ich habe auch kurz über ein Attribut nachgedacht, aber je nach Anwendungsfall (notify) braucht man ggf. mal dies und mal jenes wenn man mit einer XBMC Instanz arbeitet. Daher würde ich dies schon eher im Aufruf sehen.
Die Resumefunktion basiert ja auf dem gespeicherten letzten Wiedergabepunkt in der XBMC Datenbank. Ich würde daher mal vermuten, dass die Resumefunktion mit dem open Befehl gar nicht funktioniert, da hier ja nur ein Pfad aufgerufen wird, der ja nur von XBMC erreicht werden muss ohne zwingend in der Datenbank zu sein?! Kann mich aber auch irren und er speichert auch für eigene Pfade den Resumepunkt?! Ich würde diese Funktion eher bei den ID Aufrufen sehen.  :)

siggi85

Ich habe mal ein bisschen rum probiert in den JSON Aufruf für die openmovieid und openepisodeid den Resume Parameter erst mal standardmäßig mit aufzurufen, aber irgendwie wollte mir das nicht gelingen.
"options":{"resume":"true"}

Wie troubleshootest du in dem Modul den JSON Aufruf? Ich dachte bei verbose 5 wird der JSON Code vielleicht ins Log geschrieben aber das ist nicht so.

vbs

Meine letzte Version aus dem Thread sollte etwas gesprächiger sein und da werden auch die JSON-Nachrichten rausgeprintet IIRC (verbose 5).
Ansonsten würde ich erstmal FHEM aus der Gleichung rausnehmen und das ganze mit Browser+XBMC machen. Im XBMC am besten noch das Debug-Log aktivieren. Hier sind Beispiele, wie du JSON mit einem Browser benutzen kannst: http://forum.xbmc.org/showthread.php?tid=157996

Wenn das dann mit Browser funktioniert wie gewünscht, dann versuchen das ganze auch per FHEM zu machen.

siggi85

Alles klar gucke ich mir an! Ich habe irgendwo noch ein Perlskript liegen was einen kompletten JSON Aufruf per GET an XBMC absendet. Aber für den Resumefunktion habe ich schnell "angeblich" funktionierende Beispiele mit google gefunden, welche auch zur Syntax in der API Referenz passen.  :)

Mein Problem war, dass der JSON Aufruf im Modul ja über mehrere Funktionen zusammengebaut wird. Und als ich mehrere Zeilen JSON Code in die jeweilige Variable hinzugefügt habe, konnte ich nicht prüfen wie das nun den endgültigen JSON Request beeinflußt.  ::)
Habe schon überlegt eine NetCat Instanz aufzumachen und die Anfragen per Netzwerk dahin zu schicken, deine Logfunktion ist da natürlich eleganter.  ;)

siggi85

#17
Also der JSON Aufruf per Browser funktioniert super zum testen und auch dein XBMC Modul mit verbose 5 lässt mich die JSON Requests sehen die vom Modul erzeugt werden. Danke dafür!  :D *daumenhoch*
Jedoch komme ich wieder nicht weiter.

Folgender JSON Request separat funktioniert im Browser und öffnet das Video und startet den Resumepoint:
http://192.168.1.20:8088/jsonrpc?request={"params":{"item":{"episodeid":2767},"options":{"resume":true}},"jsonrpc":"2.0","method":"Player.Open"}

Allerdings bekomme ich das nicht im Quellcode hin...  :-\
1. Das true, wird immer in 1 umgewandelt (ich vermute durch das JSON Modul bei der Modulation.
2. Bekomme ich einen Fehler in der Perlsyntax, oder das options=>resume=>true wird im Aufruf falsch positioniert und von XBMC ignoriert. Theoretisch müsste es ca so in die XBMC_Set_Open Subroutine, aber da bekomme ich Fehler in der Perlsyntax
elsif($opt eq 'episode') {
    $params = {
      'item' => {
        'episodeid' => $path + 0
'options' => {
'resume' => true
}
      }
    };
  }


Zusätzlich habe ich noch eine Idee für das Modul! In den SB_Server bzw. SB_Player Modulen gibt es den Set Befehl "cliraw" bei dem man raw die Kommandos an Server und Player senden kann. Eine Art "jsonraw" für das XBMC Modul wäre vielleicht auch ganz nett wenn das jemand einbauen würde... ::) ;) Dann könnte man das sowohl zum testen, als auch für noch nicht implementierte Funktionen nutzen.

EDIT: Ich hoffe ich nerve nicht mit meinen Fragen zum Quellcode...  :o ::)

justme1968

ein json true kannst du mit JSON::true setzen. also so: ...
'resume' => JSON::true
...


gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

siggi85

Zitat von: justme1968 am 04 Juli 2014, 16:56:08
ein json true kannst du mit JSON::true setzen.

Klasse, das und ein Komma hat mir gefehlt, funktioniert nun.  :) Und ich kann es kaum glauben, aber ich habe sogar meine vorgeschlagene "jsonraw" Methode umsetzen können.   :o ;D
Ich wäre froh wenn ein richtiger Entwickler meine Änderungen mal prüfen könnte. Die geänderte Version habe ich im XBMC Modul Thread hochgeladen.

siggi85

#20
Update zu diesem Thema:

Ich nutze seit einiger Zeit diesen Code um die aktuelle Wiedergabe von einer XBMC Instanz auf eine andere zu schieben. Benötigt wird für dieses Skript ein dummy (d_helper) in dem während des Vorgangs ein Reading gesetzt wird. Dies soll verhindern, dass mehrere XBMC Übergänge gleichzeitig durchgeführt werden können. Es sind noch ein paar Verbesserungen notwendig (manchmal wird auf dem neuen System aufgrund von Ladezeiten keine Pause gesetzt, fehl also noch eine Art "do until pause"), aber grundsätzlich funktioniert es.

##########################################################
# XBMC to XBMC
# Aktuelles Video von einem XBMC auf einem anderen XBMC wiedergeben
sub xbmc_to_xbmc($$) {
  my ($qxbmc, $zxbmc) = @_;
  fhem "set $qxbmc statusRequest";
  fhem "set $zxbmc statusRequest";
  my $helper = ReadingsVal("d_helper","xbmc_to_xbmc",0);
  if ( $helper == 1 ) {
    fhem "define at_xbmc_to_xbmc at +00:00:05 {xbmc_to_xbmc(\"$qxbmc\",\"$zxbmc\")}";
    return 0;
  }
  fhem "setreading d_helper xbmc_to_xbmc 1";
  my $qplayStatus = ReadingsVal("$qxbmc","playStatus",0);
 
### Part fur Aktionen wenn es sich um bestimmte Quell oder Ziel XBMC Systeme handelt
    if ( $zxbmc eq "sz_xbmc" ) {
    my $twilight = ReadingsVal("my_twilight","light","6");
    fhem "set $zxbmc on";
    if ( $twilight < 5 ) {
      fhem "set sz_bulb on";
    }
  }
###

  if ( $qplayStatus eq "playing" || $qplayStatus eq "paused" ) {
    fhem "set $qxbmc stop";
  }
  fhem "define at_xbmc_to_xbmc_video at +00:00:05 {xbmc_to_xbmc_video(\"$qxbmc\",\"$zxbmc\")}";
  return 1;
}



sub xbmc_to_xbmc_video($$) {
  my ($qxbmc, $zxbmc) = @_;
  my $qtype = ReadingsVal("$qxbmc","type","nichts");
  if ( $qtype eq "episode" ) {
    my $qid = ReadingsVal("$qxbmc","episodeid",0);
    fhem "set $zxbmc openepisodeid $qid";
    fhem "set $zxbmc pause";
    my $zid = ReadingsVal("$zxbmc","episodeid",0);
      if ( $qid == $zid ) {
        fhem "set $qxbmc msg Weitergabe \"Videoweitergabe erfolgreich\"";
      }
  }
  elsif ( $qtype eq "movie" ) {
    my $qid = ReadingsVal("$qxbmc","movieid",0);
    fhem "set $zxbmc openmovieid $qid";
    fhem "set $zxbmc pause";
    my $zid = ReadingsVal("$zxbmc","movieid",0);
      if ( $qid == $zid ) {
        fhem "set $qxbmc msg Weitergabe \"Videoweitergabe erfolgreich\"";
      }
  }
  else {
    fhem "setreading d_helper xbmc_to_xbmc 0";
    return 0;
  }
  fhem "setreading d_helper xbmc_to_xbmc 0";
  return 1;
}


EDIT:
Achja, aufgerufen wird es folgendermaßen:
{xbmc_to_xbmc("wz_xbmc","sz_xbmc")}