2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-04 05:16:45 +00:00

fixed several bugs; added compatibility mode for plex

git-svn-id: https://svn.fhem.de/fhem/trunk@4670 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
dbokermann 2014-01-16 20:00:05 +00:00
parent bbe5f8d5b7
commit 1041b17dad

View File

@ -16,9 +16,9 @@ use strict;
use warnings; use warnings;
use POSIX; use POSIX;
use JSON; use JSON;
#use JSON::RPC::Client;
use Data::Dumper; use Data::Dumper;
use DevIo; use DevIo;
use IO::Socket::INET;
use MIME::Base64; use MIME::Base64;
sub XBMC_Initialize($$) sub XBMC_Initialize($$)
@ -29,7 +29,7 @@ sub XBMC_Initialize($$)
$hash->{ReadFn} = "XBMC_Read"; $hash->{ReadFn} = "XBMC_Read";
$hash->{ReadyFn} = "XBMC_Ready"; $hash->{ReadyFn} = "XBMC_Ready";
$hash->{UndefFn} = "XBMC_Undefine"; $hash->{UndefFn} = "XBMC_Undefine";
$hash->{AttrList} = "fork:enable,disable offMode:quit,hibernate,shutdown,standby"; $hash->{AttrList} = "fork:enable,disable compatibilityMode:xbmc,plex offMode:quit,hibernate,shutdown,standby " . $readingFnAttributes;
$data{RC_makenotify}{XBMC} = "XBMC_RCmakenotify"; $data{RC_makenotify}{XBMC} = "XBMC_RCmakenotify";
$data{RC_layout}{XBMC_RClayout} = "XBMC_RClayout"; $data{RC_layout}{XBMC_RClayout} = "XBMC_RClayout";
@ -75,6 +75,7 @@ sub XBMC_Define($$)
sub XBMC_Ready($) sub XBMC_Ready($)
{ {
my ($hash) = @_; my ($hash) = @_;
if($hash->{Protocol} eq 'tcp') {
if(AttrVal($hash->{NAME},'fork','disable') eq 'enable') { if(AttrVal($hash->{NAME},'fork','disable') eq 'enable') {
if($hash->{CHILDPID} && !(kill 0, $hash->{CHILDPID})) { if($hash->{CHILDPID} && !(kill 0, $hash->{CHILDPID})) {
$hash->{CHILDPID} = undef; $hash->{CHILDPID} = undef;
@ -92,6 +93,7 @@ sub XBMC_Ready($)
} else { } else {
return DevIo_OpenDev($hash, 1, "XBMC_Init"); return DevIo_OpenDev($hash, 1, "XBMC_Init");
} }
}
return undef; return undef;
} }
@ -151,11 +153,12 @@ sub XBMC_PlayerUpdate($$)
my $obj = { my $obj = {
"method" => "Player.GetProperties", "method" => "Player.GetProperties",
"params" => { "params" => {
"properties" => ["partymode", "totaltime", "repeat", "shuffled", "speed" ] "properties" => ["time","totaltime", "repeat", "shuffled", "speed" ]
#"canseek", "canchangespeed", "canmove", "canzoom", "canrotate", "canshuffle", "canrepeat" #"canseek", "canchangespeed", "canmove", "canzoom", "canrotate", "canshuffle", "canrepeat"
} }
}; };
if($playerid) { push(@{$obj->{params}->{properties}}, 'partymode') if(AttrVal($hash->{NAME},'compatibilityMode','xbmc') eq 'xbmc');
if($playerid >= 0) {
$obj->{params}->{playerid} = $playerid; $obj->{params}->{playerid} = $playerid;
XBMC_Call($hash,$obj,1); XBMC_Call($hash,$obj,1);
} }
@ -228,23 +231,16 @@ sub XBMC_ProcessNotification($$)
elsif($obj->{method} eq "Player.OnPlay") { elsif($obj->{method} eq "Player.OnPlay") {
my $id = XBMC_CreateId(); my $id = XBMC_CreateId();
my $type = $obj->{params}->{data}->{item}->{type}; my $type = $obj->{params}->{data}->{item}->{type};
if(!defined($obj->{params}->{data}->{item}->{id}) || $type eq "picture" || $type eq "unknown") { if(AttrVal($hash->{NAME},'compatibilityMode','xbmc') eq 'plex' || !defined($obj->{params}->{data}->{item}->{id}) || $type eq "picture" || $type eq "unknown") {
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
readingsBulkUpdate($hash,'playStatus','playing'); readingsBulkUpdate($hash,'playStatus','playing');
readingsBulkUpdate($hash,'type',$type); readingsBulkUpdate($hash,'type',$type);
if(defined($obj->{params}->{data}->{item}->{artist})) { if(defined($obj->{params}->{data}->{item})) {
my $artist = $obj->{params}->{data}->{item}->{artist}; foreach my $key (keys %{$obj->{params}->{data}->{item}}) {
if(ref($artist) eq 'ARRAY') { my $value = $obj->{params}->{data}->{item}->{$key};
if(int(@$artist)) { XBMC_CreateReading($hash,$key,$value);
$artist = join(',',@$artist);
} }
} }
readingsBulkUpdate($hash,'currentArtist', $artist);
}
readingsBulkUpdate($hash,'currentAlbum',$obj->{params}->{data}->{item}->{album}) if(defined($obj->{params}->{data}->{item}->{album}));
readingsBulkUpdate($hash,'currentTitle',$obj->{params}->{data}->{item}->{title}) if(defined($obj->{params}->{data}->{item}->{title}));
readingsBulkUpdate($hash,'currentTrack',$obj->{params}->{data}->{item}->{track}) if(defined($obj->{params}->{data}->{item}->{track}));
readingsBulkUpdate($hash,'currentMedia',$obj->{params}->{data}->{item}->{file}) if(defined($obj->{params}->{data}->{item}->{file}));
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
} }
elsif($type eq "song") { elsif($type eq "song") {
@ -336,7 +332,6 @@ sub XBMC_ProcessResponse($$)
my $name = $event->{name}; my $name = $event->{name};
my $type = $event->{type}; my $type = $event->{type};
my $value = ''; my $value = '';
#include song details into the event details
my $base = ''; my $base = '';
$base = $obj->{result}->{songdetails} if($type eq 'song'); $base = $obj->{result}->{songdetails} if($type eq 'song');
$base = $obj->{result}->{episodedetails} if($type eq 'episode'); $base = $obj->{result}->{episodedetails} if($type eq 'episode');
@ -348,14 +343,7 @@ sub XBMC_ProcessResponse($$)
readingsBulkUpdate($hash,'type',$type); readingsBulkUpdate($hash,'type',$type);
foreach my $key (keys %$base) { foreach my $key (keys %$base) {
my $item = $base->{$key}; my $item = $base->{$key};
if(ref($item) eq 'ARRAY') { XBMC_CreateReading($hash,$key,$item);
if(int(@$item)) {
readingsBulkUpdate($hash,$key,join(',',@$item));
}
}
else {
readingsBulkUpdate($hash,$key,$item);
}
} }
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
} }
@ -377,13 +365,30 @@ sub XBMC_ProcessResponse($$)
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
foreach my $key (keys %$properties) { foreach my $key (keys %$properties) {
my $value = $properties->{$key}; my $value = $properties->{$key};
XBMC_CreateReading($hash,$key,$value);
}
readingsEndUpdate($hash, 1);
}
}
return undef;
}
sub XBMC_CreateReading($$$) {
my $hash = shift;
my $key = shift;
my $value = shift;
if($key eq 'version') { if($key eq 'version') {
$value = $value->{major} . '.' . $value->{minor} . '-' . $value->{revision} . ' ' . $value->{tag}; 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') { elsif($key eq 'skin') {
$value = $value->{name} . '(' . $value->{id} . ')'; $value = $value->{name} . '(' . $value->{id} . ')';
} }
elsif($key eq 'totaltime') { elsif($key eq 'totaltime' || $key eq 'time') {
$value = sprintf('%02d:%02d:%02d.%03d',$value->{hours},$value->{minutes},$value->{seconds},$value->{milliseconds}); $value = sprintf('%02d:%02d:%02d.%03d',$value->{hours},$value->{minutes},$value->{seconds},$value->{milliseconds});
} }
elsif($key eq 'shuffled') { elsif($key eq 'shuffled') {
@ -407,12 +412,12 @@ sub XBMC_ProcessResponse($$)
elsif($key =~ /(album|artist|track|title)/) { elsif($key =~ /(album|artist|track|title)/) {
$key = 'current' . ucfirst($key); $key = 'current' . ucfirst($key);
} }
if(ref($value) eq 'ARRAY') {
if(int(@$value)) {
$value = join(',',@$value);
}
}
readingsBulkUpdate($hash,$key,$value); readingsBulkUpdate($hash,$key,$value);
}
readingsEndUpdate($hash, 1);
}
}
return undef;
} }
#Parses a given string and returns ($msg,$tail). If the string contains a complete message #Parses a given string and returns ($msg,$tail). If the string contains a complete message
@ -630,7 +635,7 @@ sub XBMC_Set($@)
"msg " . "msg " .
"mute:toggle,on,off volume:slider,0,1,100 quit:noArg " . "mute:toggle,on,off volume:slider,0,1,100 quit:noArg " .
"eject:noArg hibernate:noArg reboot:noArg shutdown:noArg suspend:noArg " . "eject:noArg hibernate:noArg reboot:noArg shutdown:noArg suspend:noArg " .
"videolibrary:scan,clean audiolibrary:scan,clean"; "videolibrary:scan,clean audiolibrary:scan,clean statusRequest";
return $res ; return $res ;
} }
@ -909,7 +914,8 @@ sub XBMC_HTTP_Call($$$)
my ($hash,$obj,$id) = @_; my ($hash,$obj,$id) = @_;
my $uri = "http://" . $hash->{Host} . ":" . $hash->{Port} . "/jsonrpc"; my $uri = "http://" . $hash->{Host} . ":" . $hash->{Port} . "/jsonrpc";
my $ret = XBMC_HTTP_Request(0,$uri,undef,$obj,undef,$hash->{Username},$hash->{Password}); my $ret = XBMC_HTTP_Request(0,$uri,undef,$obj,undef,$hash->{Username},$hash->{Password});
if($ret =~ /^error:(\d){3}$/) { return undef if(!$ret);
if($ret =~ /^error:(\d{3})$/) {
return "HTTP Error Code " . $1; return "HTTP Error Code " . $1;
} }
return XBMC_ProcessResponse($hash,decode_json($ret)) if($id); return XBMC_ProcessResponse($hash,decode_json($ret)) if($id);
@ -1023,7 +1029,7 @@ sub XBMC_HTTP_Request($$@)
<code>define &lt;name&gt; XBMC &lt;ip[:port]&gt; &lt;http|tcp&gt; [&lt;username&gt;] [&lt;password&gt;]</code> <code>define &lt;name&gt; XBMC &lt;ip[:port]&gt; &lt;http|tcp&gt; [&lt;username&gt;] [&lt;password&gt;]</code>
<br><br> <br><br>
This module allows you to control XBMC and receive events from XBMC.<br><br> This module allows you to control XBMC and receive events from XBMC. It can also be used to control Plex (see attribute <i>compatibilityMode</i>).<br><br>
<b>Prerequisites</b> <b>Prerequisites</b>
<ul> <ul>
@ -1031,7 +1037,8 @@ sub XBMC_HTTP_Request($$@)
<li>To use this module you will have to enable JSON-RPC. See <a href="http://wiki.xbmc.org/index.php?title=JSON-RPC_API#Enabling_JSON-RPC">here</a>.</li> <li>To use this module you will have to enable JSON-RPC. See <a href="http://wiki.xbmc.org/index.php?title=JSON-RPC_API#Enabling_JSON-RPC">here</a>.</li>
<li>The Perl module JSON is required. <br> <li>The Perl module JSON is required. <br>
On Debian/Raspbian: <code>apt-get install libjson-perl </code><br> On Debian/Raspbian: <code>apt-get install libjson-perl </code><br>
Via CPAN: <code>cpan install JSON</code></li> Via CPAN: <code>cpan install JSON</code>
To get it working on a Fritzbox the JSON module has to be installed manually.</li>
</ul> </ul>
To receive events it is necessary to use TCP. The default TCP port is 9090. Username and password are optional for TCP. Be sure to enable JSON-RPC To receive events it is necessary to use TCP. The default TCP port is 9090. Username and password are optional for TCP. Be sure to enable JSON-RPC
@ -1162,7 +1169,7 @@ sub XBMC_HTTP_Request($$@)
<li><b>mute</b> - indicates if XBMC is muted (on/off)</li> <li><b>mute</b> - indicates if XBMC is muted (on/off)</li>
<li><b>name</b> - software name (e.g. XBMC)</li> <li><b>name</b> - software name (e.g. XBMC)</li>
<li><b>originaltitle</b> - original title of the movie being played</li> <li><b>originaltitle</b> - original title of the movie being played</li>
<li><b>partymode</b> - indicates if XBMC runs in party mode (on/off)</li> <li><b>partymode</b> - indicates if XBMC runs in party mode (on/off) (not available for Plex)</li>
<li><b>playlist</b> - Possible values: add, clear, remove</li> <li><b>playlist</b> - Possible values: add, clear, remove</li>
<li><b>playStatus</b> - Indicates the player status: playing, paused, stopped</li> <li><b>playStatus</b> - Indicates the player status: playing, paused, stopped</li>
<li><b>repeat</b> - current repeat mode (one/all/off)</li> <li><b>repeat</b> - current repeat mode (one/all/off)</li>
@ -1172,6 +1179,7 @@ sub XBMC_HTTP_Request($$@)
<li><b>skin</b> - current skin of XBMC</li> <li><b>skin</b> - current skin of XBMC</li>
<li><b>songid</b> - id of the song in the music library</li> <li><b>songid</b> - id of the song in the music library</li>
<li><b>system</b> - Possible values: lowbattery, quit, restart, sleep, wake</li> <li><b>system</b> - Possible values: lowbattery, quit, restart, sleep, wake</li>
<li><b>time</b> - current position in the playing media item (only updated on play/pause)</li>
<li><b>totaltime</b> - total run time of the current media item</li> <li><b>totaltime</b> - total run time of the current media item</li>
<li><b>type</b> - type of the media item. Possible values: episode, movie, song, musicvideo, picture, unknown</li> <li><b>type</b> - type of the media item. Possible values: episode, movie, song, musicvideo, picture, unknown</li>
<li><b>version</b> - version of XBMC</li> <li><b>version</b> - version of XBMC</li>
@ -1196,6 +1204,9 @@ sub XBMC_HTTP_Request($$@)
<a name="XBMCattr"></a> <a name="XBMCattr"></a>
<b>Attributes</b> <b>Attributes</b>
<ul> <ul>
<li>compatibilityMode<br>
This module can also be used to control Plex, since the JSON Api is mostly the same, but there are some differences.
If you want to control Plex set the attribute <i>compatibilityMode</i> to <i>plex</i>.</li>
<li>offMode<br> <li>offMode<br>
Declares what should be down if the off command is executed. Possible values are <i>quit</i> (closes XBMC), <i>hibernate</i> (puts system into hibernation), Declares what should be down if the off command is executed. Possible values are <i>quit</i> (closes XBMC), <i>hibernate</i> (puts system into hibernation),
<i>suspend</i> (puts system into stand by), and <i>shutdown</i> (shuts down the system). Default value is <i>quit</i></li> <i>suspend</i> (puts system into stand by), and <i>shutdown</i> (shuts down the system). Default value is <i>quit</i></li>