70_XBMC.pm:
-added commands: openmovieid, openepisodeid, addon, jsonraw (thanks to siggi85) -fixed fork attribute to close file handles correctly -added mechanism to detect disconnects (TCP) -improved message parsing -some code refactoring -improved code formatting git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@7443 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -29,7 +29,7 @@ sub XBMC_Initialize($$)
|
||||
$hash->{ReadFn} = "XBMC_Read";
|
||||
$hash->{ReadyFn} = "XBMC_Ready";
|
||||
$hash->{UndefFn} = "XBMC_Undefine";
|
||||
$hash->{AttrList} = "fork:enable,disable compatibilityMode:xbmc,plex offMode:quit,hibernate,shutdown,standby " . $readingFnAttributes;
|
||||
$hash->{AttrList} = "fork:enable,disable compatibilityMode:xbmc,plex offMode:quit,hibernate,shutdown,standby pingInterval " . $readingFnAttributes;
|
||||
|
||||
$data{RC_makenotify}{XBMC} = "XBMC_RCmakenotify";
|
||||
$data{RC_layout}{XBMC_RClayout} = "XBMC_RClayout";
|
||||
@@ -69,6 +69,9 @@ sub XBMC_Define($$)
|
||||
else {
|
||||
return "Username and/or password missing.";
|
||||
}
|
||||
|
||||
$attr{$hash->{NAME}}{"pingInterval"} = 60;
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
@@ -84,6 +87,20 @@ sub XBMC_Ready($)
|
||||
elsif(!$hash->{CHILDPID}) {
|
||||
return if($hash->{CHILDPID} = fork);
|
||||
my $ppid = getppid();
|
||||
|
||||
### Copied from Blocking.pm
|
||||
foreach my $d (sort keys %defs) { # Close all kind of FD
|
||||
my $h = $defs{$d};
|
||||
#the following line was added by vbs to not close parent's DbLog DB handle
|
||||
$h->{DBH}->{InactiveDestroy} = 1 if ($h->{TYPE} eq 'DbLog');
|
||||
TcpServer_Close($h) if($h->{SERVERSOCKET});
|
||||
if($h->{DeviceName}) {
|
||||
require "$attr{global}{modpath}/FHEM/DevIo.pm";
|
||||
DevIo_CloseDev($h,1);
|
||||
}
|
||||
}
|
||||
### End of copied from Blocking.pm
|
||||
|
||||
while(kill 0, $ppid) {
|
||||
DevIo_OpenDev($hash, 1, "XBMC_ChildExit");
|
||||
sleep(5);
|
||||
@@ -105,6 +122,9 @@ sub XBMC_ChildExit($)
|
||||
sub XBMC_Undefine($$)
|
||||
{
|
||||
my ($hash,$arg) = @_;
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
if($hash->{Protocol} eq 'tcp') {
|
||||
DevIo_CloseDev($hash);
|
||||
}
|
||||
@@ -114,10 +134,62 @@ sub XBMC_Undefine($$)
|
||||
sub XBMC_Init($)
|
||||
{
|
||||
my ($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();
|
||||
|
||||
XBMC_Update($hash);
|
||||
|
||||
XBMC_QueueCheckConnection($hash);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub XBMC_QueueCheckConnection($;$) {
|
||||
my ($hash, $time) = @_;
|
||||
# AFAIK when using http this module is not using a persistent TCP connection
|
||||
if($hash->{Protocol} ne 'http') {
|
||||
if (!defined($time)) {
|
||||
$time = AttrVal($hash->{NAME},'pingInterval','60');
|
||||
}
|
||||
InternalTimer(time() + $time, "XBMC_CheckConnection", $hash, 0);
|
||||
}
|
||||
}
|
||||
|
||||
sub XBMC_CheckConnection($) {
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
if ($hash->{STATE} eq "disconnected") {
|
||||
# we are already disconnected
|
||||
return;
|
||||
}
|
||||
|
||||
#do not call XBMC_CheckConnection a second time before the pong had a chance to arrive
|
||||
#otherwise the connection will be considered as lost
|
||||
if ($hash->{LAST_PING} > $hash->{LAST_PONG}) {
|
||||
Log3 $name, 3, "Last ping (" . $hash->{LAST_PING} . ") is greather than last pong (" . $hash->{LAST_PONG} . ")";
|
||||
DevIo_Disconnected($hash);
|
||||
return;
|
||||
}
|
||||
|
||||
my $obj = {
|
||||
"method" => "JSONRPC.Ping",
|
||||
};
|
||||
$obj->{id} = XBMC_CreateId();
|
||||
$obj->{jsonrpc} = "2.0"; #JSON RPC version has to be passed
|
||||
|
||||
# remember: we only get here when using TCP (not HTTP)
|
||||
my $json = encode_json($obj);
|
||||
|
||||
$hash->{LAST_PING} = time();
|
||||
DevIo_SimpleWrite($hash, $json, 0);
|
||||
|
||||
#xbmc seems alive. so keep bugging it
|
||||
XBMC_QueueCheckConnection($hash);
|
||||
}
|
||||
|
||||
sub XBMC_Update($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
@@ -143,7 +215,7 @@ sub XBMC_Update($)
|
||||
}
|
||||
};
|
||||
XBMC_Call($hash,$obj,1);
|
||||
XBMC_PlayerUpdate($hash,0);
|
||||
XBMC_PlayerUpdate($hash,-1); #-1 -> update all existing players
|
||||
}
|
||||
|
||||
sub XBMC_PlayerUpdate($$)
|
||||
@@ -170,23 +242,43 @@ sub XBMC_PlayerUpdate($$)
|
||||
sub XBMC_Read($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
my $buffer = DevIo_SimpleRead($hash);
|
||||
return XBMC_ProcessRead($hash, $buffer);
|
||||
}
|
||||
|
||||
sub XBMC_ProcessRead($$)
|
||||
{
|
||||
my ($hash, $data) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $buffer = '';
|
||||
Log3($name, 5, "XBMC_ProcessRead");
|
||||
|
||||
#include previous partial message
|
||||
if(defined($hash->{PARTIAL}) && $hash->{PARTIAL}) {
|
||||
$buffer = $hash->{PARTIAL} . DevIo_SimpleRead($hash);
|
||||
Log3($name, 5, "XBMC_Read: PARTIAL: " . $hash->{PARTIAL});
|
||||
$buffer = $hash->{PARTIAL};
|
||||
}
|
||||
else {
|
||||
$buffer = DevIo_SimpleRead($hash);
|
||||
Log3($name, 5, "No PARTIAL buffer");
|
||||
}
|
||||
|
||||
Log3($name, 5, "XBMC_Read: Incoming data: " . $data);
|
||||
|
||||
$buffer = $buffer . $data;
|
||||
Log3($name, 5, "XBMC_Read: Current processing buffer (PARTIAL + incoming data): " . $buffer);
|
||||
|
||||
my ($msg,$tail) = XBMC_ParseMsg($buffer);
|
||||
#processes all complete messages
|
||||
while($msg) {
|
||||
my $obj = decode_json($msg);
|
||||
Log 5, "XBMC received message:" . $msg;
|
||||
Log3($name, 5, "XBMC_Read: Decoding JSON message. Length: " . length($msg) . " Content: " . $msg);
|
||||
my $obj = JSON->new->utf8(0)->decode($msg);
|
||||
#it is a notification if a method name is present
|
||||
if(defined($obj->{method})) {
|
||||
XBMC_ProcessNotification($hash,$obj);
|
||||
}
|
||||
elsif(defined($obj->{error})) {
|
||||
Log3($name, 3, "XBMC_Read: Received error message: " . $msg);
|
||||
}
|
||||
#otherwise it is a answer of a request
|
||||
else {
|
||||
XBMC_ProcessResponse($hash,$obj);
|
||||
@@ -194,41 +286,14 @@ sub XBMC_Read($)
|
||||
($msg,$tail) = XBMC_ParseMsg($tail);
|
||||
}
|
||||
$hash->{PARTIAL} = $tail;
|
||||
Log 5, "Tail:" . $tail;
|
||||
Log3($name, 5, "XBMC_Read: Tail: " . $tail);
|
||||
Log3($name, 5, "XBMC_Read: PARTIAL: " . $hash->{PARTIAL});
|
||||
}
|
||||
|
||||
sub XBMC_ProcessNotification($$)
|
||||
sub XBMC_PlayerOnPlay($$)
|
||||
{
|
||||
my ($hash,$obj) = @_;
|
||||
#React on volume change - http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Application.OnVolumeChanged
|
||||
if($obj->{method} eq "Application.OnVolumeChanged") {
|
||||
readingsBeginUpdate($hash);
|
||||
readingsBulkUpdate($hash,'volume',$obj->{params}->{data}->{volume});
|
||||
readingsBulkUpdate($hash,'mute',($obj->{params}->{data}->{muted} ? 'on' : 'off'));
|
||||
readingsEndUpdate($hash, 1);
|
||||
}
|
||||
#React on play, pause and stop
|
||||
#http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Player.OnPlay
|
||||
#http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Player.OnPause
|
||||
#http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Player.OnStop
|
||||
elsif($obj->{method} eq "Player.OnPropertyChanged") {
|
||||
XBMC_PlayerUpdate($hash,$obj->{params}->{data}->{player}->{playerid});
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnSeek") {
|
||||
#XBMC_PlayerUpdate($hash,$obj->{params}->{data}->{player}->{playerid});
|
||||
Log 3, "Discard Player.OnSeek event because it is irrelevant";
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnSpeedChanged") {
|
||||
#XBMC_PlayerUpdate($hash,$obj->{params}->{data}->{player}->{playerid});
|
||||
Log 3, "Discard Player.OnSpeedChanged event because it is irrelevant";
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnStop") {
|
||||
readingsSingleUpdate($hash,"playStatus",'stopped',1);
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnPause") {
|
||||
readingsSingleUpdate($hash,"playStatus",'paused',1);
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnPlay") {
|
||||
my $name = $hash->{NAME};
|
||||
my $id = XBMC_CreateId();
|
||||
my $type = $obj->{params}->{data}->{item}->{type};
|
||||
if(AttrVal($hash->{NAME},'compatibilityMode','xbmc') eq 'plex' || !defined($obj->{params}->{data}->{item}->{id}) || $type eq "picture" || $type eq "unknown") {
|
||||
@@ -316,8 +381,55 @@ sub XBMC_ProcessNotification($$)
|
||||
}
|
||||
XBMC_PlayerUpdate($hash,$obj->{params}->{data}->{player}->{playerid});
|
||||
}
|
||||
|
||||
sub XBMC_ProcessNotification($$)
|
||||
{
|
||||
my ($hash,$obj) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
#React on volume change - http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Application.OnVolumeChanged
|
||||
if($obj->{method} eq "Application.OnVolumeChanged") {
|
||||
readingsBeginUpdate($hash);
|
||||
readingsBulkUpdate($hash,'volume',$obj->{params}->{data}->{volume});
|
||||
readingsBulkUpdate($hash,'mute',($obj->{params}->{data}->{muted} ? 'on' : 'off'));
|
||||
readingsEndUpdate($hash, 1);
|
||||
}
|
||||
#React on play, pause and stop
|
||||
#http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Player.OnPlay
|
||||
#http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Player.OnPause
|
||||
#http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Player.OnStop
|
||||
elsif($obj->{method} eq "Player.OnPropertyChanged") {
|
||||
XBMC_PlayerUpdate($hash,$obj->{params}->{data}->{player}->{playerid});
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnSeek") {
|
||||
#XBMC_PlayerUpdate($hash,$obj->{params}->{data}->{player}->{playerid});
|
||||
Log3($name, 4, "Discard Player.OnSeek event because it is irrelevant");
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnSpeedChanged") {
|
||||
#XBMC_PlayerUpdate($hash,$obj->{params}->{data}->{player}->{playerid});
|
||||
Log3($name, 3, "Discard Player.OnSpeedChanged event because it is irrelevant");
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnStop") {
|
||||
readingsSingleUpdate($hash,"playStatus",'stopped',1);
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnPause") {
|
||||
readingsSingleUpdate($hash,"playStatus",'paused',1);
|
||||
}
|
||||
elsif($obj->{method} eq "Player.OnPlay") {
|
||||
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);
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
@@ -362,6 +474,7 @@ sub XBMC_ProcessResponse($$)
|
||||
else {
|
||||
my $properties = $obj->{result};
|
||||
if($properties && $properties ne 'OK') {
|
||||
if ($properties ne 'pong') {
|
||||
readingsBeginUpdate($hash);
|
||||
foreach my $key (keys %$properties) {
|
||||
my $value = $properties->{$key};
|
||||
@@ -369,6 +482,11 @@ sub XBMC_ProcessResponse($$)
|
||||
}
|
||||
readingsEndUpdate($hash, 1);
|
||||
}
|
||||
else {
|
||||
#Pong
|
||||
$hash->{LAST_PONG} = time();
|
||||
}
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
@@ -490,6 +608,15 @@ sub XBMC_Set($@)
|
||||
elsif($cmd eq 'open') {
|
||||
return XBMC_Set_Open($hash, 'file', @args);
|
||||
}
|
||||
elsif($cmd eq 'openmovieid') {
|
||||
return XBMC_Set_Open($hash, 'movie', @args);
|
||||
}
|
||||
elsif($cmd eq 'openepisodeid') {
|
||||
return XBMC_Set_Open($hash, 'episode', @args);
|
||||
}
|
||||
elsif($cmd eq 'addon') {
|
||||
return XBMC_Set_Addon($hash, @args);
|
||||
}
|
||||
elsif($cmd eq 'shuffle') {
|
||||
return XBMC_Set_Shuffle($hash, @args);
|
||||
}
|
||||
@@ -530,6 +657,10 @@ sub XBMC_Set($@)
|
||||
my $action = $args[0]; #http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Input.Action
|
||||
return XBMC_Call($hash,{'method' => 'Input.ExecuteAction', 'params' => { 'action' => $action}},0);
|
||||
}
|
||||
elsif($cmd eq 'jsonraw') {
|
||||
my $action = join("",@args);
|
||||
return XBMC_Call_raw($hash,$action,0);
|
||||
}
|
||||
elsif($cmd eq 'showcodec') {
|
||||
return XBMC_Simple_Call($hash,'Input.ShowCodec');
|
||||
}
|
||||
@@ -603,7 +734,7 @@ sub XBMC_Set($@)
|
||||
my $res = "Unknown argument " . $cmd . ", choose one of " .
|
||||
"off play:all,audio,video,picture playpause:all,audio,video,picture pause:all,audio,video,picture " .
|
||||
"prev:all,audio,video,picture next:all,audio,video,picture goto stop:all,audio,video,picture " .
|
||||
"open opendir shuffle:toggle,on,off repeat:one,all,off volumeUp:noArg volumeDown:noArg " .
|
||||
"open opendir openmovieid openepisodeid addon shuffle:toggle,on,off repeat:one,all,off volumeUp:noArg volumeDown:noArg " .
|
||||
"back:noArg contextmenu:noArg down:noArg home:noArg info:noArg left:noArg " .
|
||||
"right:noArg select:noArg send exec:left,right," .
|
||||
"up,down,pageup,pagedown,select,highlight,parentdir,parentfolder,back," .
|
||||
@@ -635,7 +766,7 @@ sub XBMC_Set($@)
|
||||
"msg " .
|
||||
"mute:toggle,on,off volume:slider,0,1,100 quit:noArg " .
|
||||
"eject:noArg hibernate:noArg reboot:noArg shutdown:noArg suspend:noArg " .
|
||||
"videolibrary:scan,clean audiolibrary:scan,clean statusRequest";
|
||||
"videolibrary:scan,clean audiolibrary:scan,clean statusRequest jsonraw";
|
||||
return $res ;
|
||||
|
||||
}
|
||||
@@ -665,6 +796,24 @@ sub XBMC_Set_Open($@)
|
||||
'directory' => $path
|
||||
}
|
||||
};
|
||||
} elsif($opt eq 'movie') {
|
||||
$params = {
|
||||
'item' => {
|
||||
'movieid' => $path +0
|
||||
},
|
||||
'options' => {
|
||||
'resume' => JSON::true
|
||||
}
|
||||
};
|
||||
} elsif($opt eq 'episode') {
|
||||
$params = {
|
||||
'item' => {
|
||||
'episodeid' => $path +0
|
||||
},
|
||||
'options' => {
|
||||
'resume' => JSON::true
|
||||
}
|
||||
};
|
||||
}
|
||||
my $obj = {
|
||||
'method' => 'Player.Open',
|
||||
@@ -673,6 +822,29 @@ sub XBMC_Set_Open($@)
|
||||
return XBMC_Call($hash,$obj,0);
|
||||
}
|
||||
|
||||
sub XBMC_Set_Addon($@)
|
||||
{
|
||||
my $hash = shift;
|
||||
my $params;
|
||||
my $attr = join(" ", @_);
|
||||
$attr =~ /(".*?"|'.*?'|[^ ]+)[ \t]+(".*?"|'.*?'|[^ ]+)[ \t]+(".*?"|'.*?'|[^ ]+)$/;
|
||||
my $addonid = $1;
|
||||
my $paramname = $2;
|
||||
my $paramvalue = $3;
|
||||
# printf "$1 $2 $3";
|
||||
$params = {
|
||||
'addonid' => $addonid,
|
||||
'params' => {
|
||||
$paramname => $paramvalue
|
||||
}
|
||||
};
|
||||
my $obj = {
|
||||
'method' => 'Addons.ExecuteAddon',
|
||||
'params' => $params
|
||||
};
|
||||
return XBMC_Call($hash,$obj,0);
|
||||
}
|
||||
|
||||
sub XBMC_Set_Message($@)
|
||||
{
|
||||
my $hash = shift;
|
||||
@@ -860,12 +1032,14 @@ sub XBMC_Set_Mute($@)
|
||||
sub XBMC_Call($$$)
|
||||
{
|
||||
my ($hash,$obj,$id) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
#add an ID otherwise XBMC will not respond
|
||||
if($id &&!defined($obj->{id})) {
|
||||
$obj->{id} = XBMC_CreateId();
|
||||
}
|
||||
$obj->{jsonrpc} = "2.0"; #JSON RPC version has to be passed
|
||||
my $json = encode_json($obj);
|
||||
Log3($name, 5, "XBMC_Call: Sending: " . $json);
|
||||
if($hash->{Protocol} eq 'http') {
|
||||
return XBMC_HTTP_Call($hash,$json,$id);
|
||||
}
|
||||
@@ -874,6 +1048,19 @@ sub XBMC_Call($$$)
|
||||
}
|
||||
}
|
||||
|
||||
sub XBMC_Call_raw($$$)
|
||||
{
|
||||
my ($hash,$obj,$id) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
Log3($name, 5, "XBMC_Call: Sending: " . $obj);
|
||||
if($hash->{Protocol} eq 'http') {
|
||||
return XBMC_HTTP_Call($hash,$obj,$id);
|
||||
}
|
||||
else {
|
||||
return XBMC_TCP_Call($hash,$obj);
|
||||
}
|
||||
}
|
||||
|
||||
sub XBMC_CreateId()
|
||||
{
|
||||
return int(rand(1000000));
|
||||
@@ -918,7 +1105,7 @@ sub XBMC_HTTP_Call($$$)
|
||||
if($ret =~ /^error:(\d{3})$/) {
|
||||
return "HTTP Error Code " . $1;
|
||||
}
|
||||
return XBMC_ProcessResponse($hash,decode_json($ret)) if($id);
|
||||
return XBMC_ProcessResponse($hash,JSON->new->utf8(0)->decode($ret)) if($id);
|
||||
return undef;
|
||||
}
|
||||
|
||||
@@ -930,7 +1117,7 @@ sub XBMC_HTTP_Request($$@)
|
||||
|
||||
my $displayurl= $quiet ? "<hidden>" : $url;
|
||||
if($url !~ /^(http|https):\/\/([^:\/]+)(:\d+)?(\/.*)$/) {
|
||||
Log 1, "XBMC_HTTP_Request $displayurl: malformed or unsupported URL";
|
||||
Log(1, "XBMC_HTTP_Request $displayurl: malformed or unsupported URL");
|
||||
return undef;
|
||||
}
|
||||
|
||||
@@ -948,7 +1135,7 @@ sub XBMC_HTTP_Request($$@)
|
||||
if($protocol eq "https") {
|
||||
eval "use IO::Socket::SSL";
|
||||
if($@) {
|
||||
Log 1, $@;
|
||||
Log(1, $@);
|
||||
} else {
|
||||
$conn = IO::Socket::SSL->new(PeerAddr=>"$host:$port", Timeout=>$timeout);
|
||||
}
|
||||
@@ -956,7 +1143,7 @@ sub XBMC_HTTP_Request($$@)
|
||||
$conn = IO::Socket::INET->new(PeerAddr=>"$host:$port", Timeout=>$timeout);
|
||||
}
|
||||
if(!$conn) {
|
||||
Log 1, "XBMC_HTTP_Request $displayurl: Can't connect to $protocol://$host:$port\n";
|
||||
Log(1, "XBMC_HTTP_Request $displayurl: Can't connect to $protocol://$host:$port\n");
|
||||
undef $conn;
|
||||
return undef;
|
||||
}
|
||||
@@ -988,7 +1175,7 @@ sub XBMC_HTTP_Request($$@)
|
||||
vec($rin, $conn->fileno(), 1) = 1;
|
||||
my $nfound = select($rout=$rin, undef, undef, $timeout);
|
||||
if($nfound <= 0) {
|
||||
Log 1, "XBMC_HTTP_Request $displayurl: Select timeout/error: $!";
|
||||
Log(1, "XBMC_HTTP_Request $displayurl: Select timeout/error: $!");
|
||||
undef $conn;
|
||||
return undef;
|
||||
}
|
||||
@@ -1001,11 +1188,11 @@ sub XBMC_HTTP_Request($$@)
|
||||
$ret=~ s/(.*?)\r\n\r\n//s; # Not greedy: switch off the header.
|
||||
my @header= split("\r\n", $1);
|
||||
my $hostpath= $quiet ? "<hidden>" : $host . $path;
|
||||
Log 4, "XBMC_HTTP_Request $displayurl: Got data, length: ".length($ret);
|
||||
Log(4, "XBMC_HTTP_Request $displayurl: Got data, length: ".length($ret));
|
||||
if(!length($ret)) {
|
||||
Log 4, "XBMC_HTTP_Request $displayurl: Zero length data, header follows...";
|
||||
Log(4, "XBMC_HTTP_Request $displayurl: Zero length data, header follows...");
|
||||
for (@header) {
|
||||
Log 4, "XBMC_HTTP_Request $displayurl: $_";
|
||||
Log(4, "XBMC_HTTP_Request $displayurl: $_");
|
||||
}
|
||||
}
|
||||
undef $conn;
|
||||
@@ -1099,6 +1286,9 @@ sub XBMC_HTTP_Request($$@)
|
||||
<li><b>repeat <one|all|off> [<audio|video|picture>]</b> - Sets the repeat mode.</li>
|
||||
<li><b>open <URI></b> - Plays the resource located at the URI (can be a url or a file)</li>
|
||||
<li><b>opendir <path></b> - Plays the content of the directory</li>
|
||||
<li><b>openmovieid <path></b> - Plays the movie of the id</li>
|
||||
<li><b>openepisodeid <path></b> - Plays the episode of the id</li>
|
||||
<li><b>addon <addonid> <parametername> <parametervalue></b> - Executes addon with one Parameter, for example set xbmc addon script.json-cec command activate</li>
|
||||
</ul>
|
||||
<br>Input related commands:<br>
|
||||
<ul>
|
||||
@@ -1114,6 +1304,7 @@ sub XBMC_HTTP_Request($$@)
|
||||
<li><b>showcodec</b> - Shows Codec information</li>
|
||||
<li><b>exec <action></b> - Execute an input action. All available actions are listed <a href="http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v6#Input.Action">here</a></li>
|
||||
<li><b>send <text></b> - Sends <text> as input to XBMC</li>
|
||||
<li><b>jsonraw</b> - Sends raw JSON data to XBMC</li>
|
||||
</ul>
|
||||
<br>Libary related commands:<br>
|
||||
<ul>
|
||||
|
||||
Reference in New Issue
Block a user