From f59c2898c34894ebb38ae8eef1083f6647fb7045 Mon Sep 17 00:00:00 2001 From: vbs2 Date: Tue, 20 Jan 2015 21:52:44 +0000 Subject: [PATCH] 70_XBMC: new reading is3DFile, clear readings on stop, improved JSON seperator git-svn-id: https://svn.fhem.de/fhem/trunk@7646 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 3 ++ fhem/FHEM/70_XBMC.pm | 117 ++++++++++++++++++++++++++++++++----------- 2 files changed, 92 insertions(+), 28 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 6a818af35..a304d2e8a 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,8 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: 70_XBMC.pm: clear readings when stopping media + - feature: 70_XBMC.pm: new reading is3DFile for 3D files + - bugfix: 70_XBMC.pm: improved JSON separator - added 73_km200: More services added. - changed 73_km200: Fhem get-command is able to return raw. - bugfix 73_km200: Handling of unknown attributes corrected. diff --git a/fhem/FHEM/70_XBMC.pm b/fhem/FHEM/70_XBMC.pm index a429b35e6..df8b2a2ca 100644 --- a/fhem/FHEM/70_XBMC.pm +++ b/fhem/FHEM/70_XBMC.pm @@ -177,7 +177,10 @@ sub XBMC_Undefine($$) sub XBMC_Init($) { my ($hash) = @_; - + + XBMC_ResetMediaReadings($hash); + XBMC_ResetPlayerReadings($hash); + #since we just successfully connected to XBMC I guess its safe to assume the device is awake readingsSingleUpdate($hash,"system","wake",1); $hash->{LAST_PING} = $hash->{LAST_PONG} = time(); @@ -244,13 +247,7 @@ sub XBMC_Update($) } }; XBMC_Call($hash,$obj,1); - #$obj = { - # "method" => "System.GetProperties", - # "params" => { - # "properties" => ["canshutdown", "cansuspend", "canhibernate", "canreboot"] - # } - #}; - #XBMC_Call($hash,$obj,1); + $obj = { "method" => "GUI.GetProperties", "params" => { @@ -311,7 +308,7 @@ sub XBMC_ProcessRead($$) $buffer = $buffer . $data; Log3($name, 5, "XBMC_Read: Current processing buffer (PARTIAL + incoming data): " . $buffer); - my ($msg,$tail) = XBMC_ParseMsg($buffer); + my ($msg,$tail) = XBMC_ParseMsg($hash, $buffer); #processes all complete messages while($msg) { Log3($name, 5, "XBMC_Read: Decoding JSON message. Length: " . length($msg) . " Content: " . $msg); @@ -327,7 +324,7 @@ sub XBMC_ProcessRead($$) else { XBMC_ProcessResponse($hash,$obj); } - ($msg,$tail) = XBMC_ParseMsg($tail); + ($msg,$tail) = XBMC_ParseMsg($hash, $tail); } $hash->{PARTIAL} = $tail; Log3($name, 5, "XBMC_Read: Tail: " . $tail); @@ -335,6 +332,47 @@ sub XBMC_ProcessRead($$) return; } +sub XBMC_ResetMediaReadings($) +{ + my ($hash) = @_; + readingsBeginUpdate($hash); + readingsBulkUpdate($hash, "currentMedia", "" ); + readingsBulkUpdate($hash, "currentOriginaltitle", "" ); + readingsBulkUpdate($hash, "currentShowtitle", "" ); + readingsBulkUpdate($hash, "currentTitle", "" ); + readingsBulkUpdate($hash, "episode", "" ); + readingsBulkUpdate($hash, "episodeid", "" ); + readingsBulkUpdate($hash, "season", "" ); + readingsBulkUpdate($hash, "label", "" ); + readingsBulkUpdate($hash, "movieid", "" ); + readingsBulkUpdate($hash, "playlist", "" ); + readingsBulkUpdate($hash, "type", "" ); + readingsBulkUpdate($hash, "year", "" ); + readingsBulkUpdate($hash, "is3DFile", "" ); + + readingsBulkUpdate($hash, "currentAlbum", "" ); + readingsBulkUpdate($hash, "currentArtist", "" ); + readingsBulkUpdate($hash, "songid", "" ); + readingsBulkUpdate($hash, "currentTrack", "" ); + + readingsEndUpdate($hash, 1); +} + +sub XBMC_ResetPlayerReadings($) +{ + my ($hash) = @_; + readingsBeginUpdate($hash); + readingsBulkUpdate($hash, "time", "" ); + readingsBulkUpdate($hash, "totaltime", "" ); + readingsBulkUpdate($hash, "shuffle", "" ); + readingsBulkUpdate($hash, "repeat", "" ); + readingsBulkUpdate($hash, "speed", "" ); + readingsBulkUpdate($hash, "partymode", "" ); + + readingsBulkUpdate($hash, "playStatus", "stopped" ); + readingsEndUpdate($hash, 1); +} + sub XBMC_PlayerOnPlay($$) { my ($hash,$obj) = @_; @@ -468,26 +506,36 @@ sub XBMC_ProcessNotification($$) Log3($name, 4, "Discard Player.OnSpeedChanged event because it is irrelevant"); } elsif($obj->{method} eq "Player.OnStop") { + XBMC_ResetMediaReadings($hash); + XBMC_ResetPlayerReadings($hash); readingsSingleUpdate($hash,"playStatus",'stopped',1); } elsif($obj->{method} eq "Player.OnPause") { readingsSingleUpdate($hash,"playStatus",'paused',1); } elsif($obj->{method} eq "Player.OnPlay") { + XBMC_ResetMediaReadings($hash); XBMC_PlayerOnPlay($hash, $obj); } elsif($obj->{method} =~ /(.*).On(.*)/) { readingsSingleUpdate($hash,lc($1),lc($2),1); - if ((lc($1) eq "system") and (lc($2) eq "sleep")) { - Log3($name, 3, "XBMC notified that it is going to sleep"); - #if we immediatlely close our DevIO then fhem will instantly try to reconnect which might - #succeed because XBMC needs a moment to actually shutdown. - #So cancel the current timer, fake that the last pong has arrived ages ago - #and force a connection check in some seconds when we think XBMC actually has shut down - $hash->{LAST_PONG} = 0; - RemoveInternalTimer($hash); - XBMC_QueueCheckConnection($hash, 5); + if (lc($1) eq "system") { + if ((lc($2) eq "quit") or (lc($2) eq "restart") or (lc($2) eq "sleep")) { + XBMC_ResetMediaReadings($hash); + XBMC_ResetPlayerReadings($hash); + } + + if (lc($2) eq "sleep") { + Log3($name, 3, "XBMC notified that it is going to sleep"); + #if we immediatlely close our DevIO then fhem will instantly try to reconnect which might + #succeed because XBMC needs a moment to actually shutdown. + #So cancel the current timer, fake that the last pong has arrived ages ago + #and force a connection check in some seconds when we think XBMC actually has shut down + $hash->{LAST_PONG} = 0; + RemoveInternalTimer($hash); + XBMC_QueueCheckConnection($hash, 5); + } } } return undef; @@ -550,20 +598,26 @@ sub XBMC_ProcessResponse($$) return undef; } +sub XBMC_is3DFile($$) { + my ($hash, $filename) = @_; + + return ($filename =~ /([-. _]3d[-. _]|.*3dbd.*)/i); +} + sub XBMC_CreateReading($$$) { my $hash = shift; my $key = shift; my $value = shift; if($key eq 'version') { - my $version = ''; - $version = $value->{major}; - $version .= '.' . $value->{minor} if(defined($value->{minor})); - $version .= '-' . $value->{revision} if(defined($value->{revision})); - $version .= ' ' . $value->{tag} if(defined($value->{tag})); - $value = $version; + my $version = ''; + $version = $value->{major}; + $version .= '.' . $value->{minor} if(defined($value->{minor})); + $version .= '-' . $value->{revision} if(defined($value->{revision})); + $version .= ' ' . $value->{tag} if(defined($value->{tag})); + $value = $version; } elsif($key eq 'skin') { - $value = $value->{name} . '(' . $value->{id} . ')'; + $value = $value->{name} . '(' . $value->{id} . ')'; } elsif($key eq 'totaltime' || $key eq 'time') { $value = sprintf('%02d:%02d:%02d.%03d',$value->{hours},$value->{minutes},$value->{seconds},$value->{milliseconds}); @@ -585,6 +639,9 @@ sub XBMC_CreateReading($$$) { } elsif($key eq 'file') { $key = 'currentMedia'; + + my $is3D = XBMC_is3DFile($hash, $value); + XBMC_CreateReading($hash, "is3DFile", $is3D ? "on" : "off"); } elsif($key =~ /(album|artist|track|title)/) { $key = 'current' . ucfirst($key); @@ -600,9 +657,10 @@ sub XBMC_CreateReading($$$) { #Parses a given string and returns ($msg,$tail). If the string contains a complete message #(equal number of curly brackets) the return value $msg will contain this message. The #remaining string is return in form of the $tail variable. -sub XBMC_ParseMsg($) +sub XBMC_ParseMsg($$) { - my ($buffer) = @_; + my ($hash, $buffer) = @_; + my $name = $hash->{NAME}; my $open = 0; my $close = 0; my $msg = ''; @@ -612,6 +670,9 @@ sub XBMC_ParseMsg($) if($open == $close && $open > 0) { $tail .= $c; } + elsif(($open == $close) && ($c ne '{')) { + Log3($name, 5, "XBMC_ParseMsg: Garbage character before message: " . $c); + } else { if($c eq '{') { $open++;