Kodi Community Forum

Full Version: JSON-RPC (JSON Remote Procedure Call) interface protocol in development for XBMC
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
(2012-05-25, 10:55)mikebzh44 Wrote: [ -> ]I start the slideshow with :

Code:
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Player.Open", "params": {"item": {"playlistid": 2, "position":0}}, "id": 1}' )

The slideshow start with the right picture but other pictures seem to be played in random mode.

Is there a way to play playlist in item order ? Those parameters cannot be used with playlistid ?

Code:
{
          "additionalProperties": false,
          "type": "object",
          "properties": {
            "path": {
              "required": true,
              "type": "string"
            },
            "random": {
              "default": true,
              "type": "boolean"
            },
            "recursive": {
              "default": true,
              "type": "boolean"
            }
          }

These can only be used if all your pictures are in the same directory. IIRC slideshows by default start in random mode so you will need to also pass the "shuffled": false property in the "options" parameter, i.e.:
Code:
{ "jsonrpc": "2.0", "method": "Player.Open", "params": { "item": { "playlistid": 2, "position": 0 }, "options": { "shuffled": false } }, "id": 1 }
OK. Thanks for the tip but pictures can be stored in differents directories.

My playlist :
C:\Pictures\Children\Photo1.jpg
C:\Pictures\Holidays\Photo1.jpg
C:\Pictures\Sports\Photo1.jpg

So shuffled is useless ?

"options" parameters is not referenced in documentation ??

Code:
{
  "returns": {
    "type": "string"
  },
  "params": [
    {
      "type": [
        {
          "additionalProperties": false,
          "type": "object",
          "properties": {
            "position": {
              "default": 0,
              "$ref": "Playlist.Position"
            },
            "playlistid": {
              "required": true,
              "$ref": "Playlist.Id"
            }
          }
        },
        {
          "$ref": "Playlist.Item"
        },
        {
          "additionalProperties": false,
          "type": "object",
          "properties": {
            "path": {
              "required": true,
              "type": "string"
            },
            "random": {
              "default": true,
              "type": "boolean"
            },
            "recursive": {
              "default": true,
              "type": "boolean"
            }
          }
        }
      ],
      "name": "item"
    }
  ],
  "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."
}

http://wiki.xbmc.org/index.php?title=JSO...layer.Open
Ah the "options" parameter is only available in nightly builds (JSON-RPC API v5) and not in Eden (JSON-RPC API v4). If you are targeting Eden then you will need to start the slideshow with Player.Open and afterwards execute Player.UnShuffle.

But I have to say that the slideshow support is rather poor because XBMC's whole slideshow implementation/support is very basic and poor. So JSON-RPC methods in the Player and Playlist namespace may behave differently for slideshows than they do for music and video playback/items.
OK. As my target is Eden Stable, I will keep JSON V4.

SlideShow is basic but I only need to display 10 pictures from a Home widget so everything is OK for me.

Thanks a lot for your answers.

Have a nice and sunny week-end Wink
There seems to be a problem with adding directories that are not in the library:
Code:
{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"item": {"directory": "/mnt/media/audio/Art Brut/Bang Bang Rock 'n Roll/"}, "playlistid": 0}, "id": 1}
Works and is in library.
Code:
{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"item": {"directory": "/mnt/media/music/A/How Ace Are Buildings/"}, "playlistid": 0}, "id": 1}
Does not work and is not in library. Invalid params is the error.

Am I missing something?
(2012-05-25, 10:02)Montellese Wrote: [ -> ]Yes using Playlist.Add is the right way but there are three errors in your request. First of all the first request is wrong, as there's no "type" property in the "item" parameter. The second request you posted looks better but the "playlistid" for picture playlists must be 2 and not 1 (1 is for video), you need to escape the backslashes in your path and the first "id" property in the "item" parameter does not belong there either. So it should look like this:
Code:
xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "Playlist.Add", "params": { "playlistid": 2, "item": { "file": "C:\\Photos\\Leane_20111207_195415.jpg" } }, "id": 1 }')
There is somethind that I don't understand with \ and \\

Pictures path that have to be displayed in slideshow are stored in CommonCache.

Code:
cache.table_name = "MyPicsDB"
        _count = int(cache.get("MyPicsDB%s.Nb" %( _method )))
        for _i in range( 1,_count+1 ):
            _path = cache.get("MyPicsDB%s.%d.Path" %( _method, _i ))
            print("MyPicsDB%s.%d.Path=" %( _method, _i ), _path)
            _query = '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "%s"}}, "id": 1}' %(_path)
            print("QUERY=",_query)
            _json_query = xbmc.executeJSONRPC(_query)
            _json_query = unicode(_json_query, 'utf-8', errors='ignore')
            _json_pl_response = simplejson.loads(_json_query)

So _path is OK and get \\ as _query but get a parse error from JSON :

Code:
10:32:57 T:2524  NOTICE: ('MyPicsDBLatest.1.Path=', u'C:\\Photos\\Leane_20111207_195415.jpg')
10:32:57 T:2524  NOTICE: ('QUERY=', u'{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "C:\\Photos\\Leane_20111207_195415.jpg"}}, "id": 1}')
10:32:57 T:2524   ERROR: JSONRPC: Failed to parse '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "C:\Photos\Leane_20111207_195415.jpg"}}, "id": 1}'
10:32:57 T:2524  NOTICE: ('MyPicsDBLatest.2.Path=', u'C:\\Photos\\Leane_20110901_200610.jpg')
10:32:57 T:2524  NOTICE: ('QUERY=', u'{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "C:\\Photos\\Leane_20110901_200610.jpg"}}, "id": 1}')
10:32:57 T:2524   ERROR: JSONRPC: Failed to parse '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "C:\Photos\Leane_20110901_200610.jpg"}}, "id": 1}'
10:32:57 T:2524  NOTICE: ('MyPicsDBLatest.3.Path=', u'C:\\Photos\\Leane_20110729_111400.jpg')
10:32:57 T:2524  NOTICE: ('QUERY=', u'{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "C:\\Photos\\Leane_20110729_111400.jpg"}}, "id": 1}')
10:32:57 T:2524   ERROR: JSONRPC: Failed to parse '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "C:\Photos\Leane_20110729_111400.jpg"}}, "id": 1}'

I have try with :

Code:
_query = '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "%s"}}, "id": 1}' %(normpath(_path))

But same issue Sad

The only way to get slideshow to work is :

Code:
_query = '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "%s"}}, "id": 1}' %(_path.replace("\\","\\\\"))

It work on Windows but not on Linux :

Code:
19:57:57 T:2864687936   DEBUG: JSONRPC: Incoming request: {"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "/media/Disq500GO/Mes Photos/mont saint michel 2011/IMG_3469.JPG"}}, "id": 1}
19:57:57 T:2864687936   DEBUG: JSONRPC: Calling playlist.add
19:57:57 T:2864687936    INFO: -->Python script returned the following error<--
19:57:57 T:2864687936   ERROR: Error Type: <type 'exceptions.UnicodeEncodeError'>
19:57:57 T:2864687936   ERROR: Error Contents: 'ascii' codec can't encode character u'\xfb' in position 132: ordinal not in range(128)

How can I send the good path to JSON ?

Thanks.
I have no clue about python so I can't really help you there. All I can tell you is that in JSON (and in many (other) programming languages) the backslash \ is used as an escape character so you need to escape it with another backslash. If python uses the backslash as an escape character as well you'll need to escape it again (which is probably why you need the _path.replace("\\", "\\\\")).

Forward slashes / (which are used by linux for paths) don't need to be escaped.
OK.

Thanks.
OK for \ and \\ but I got an other issue with accent Sad

File on my PC :

C:\Photos\Août 2010.jpg

This path is stored on CommonCache and when I request CommonCache, I get UTF-8 String I suppose :

Code:
u'C:\\Photos\\Ao\xfbt 2010.jpg'

But if I want to add this path to Playlist with this code :

Code:
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "%s"}}, "id": 1}' %(_path))

I get an error :

Code:
Error Contents: 'ascii' codec can't encode character u'\xfb' in position 106: ordinal not in range(128)

I gess that JSON don't want UTF-8 string as if I call JSON this way :

Code:
xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "C:\\\\Photos\\\\Août 2010.jpg"}}, "id": 1}')

File is added to Playlist and played.

I've tried many things to encode/decode path from UTF-8 to ASCII or LATIN1 but now I'm lost and I don't know what to do Sad
This is again a python issue. In python unicode strings (as the one you retrieve from CommonCache seems to be) and standard strings are not interchangeable so you have to do the conversion between them manually. xbmc.executeJSONRPC() expects an UTF-8 encoded string and not a "python unicode string" so python complains when you try to put a unicode string into a standard string (even if its UTF-8 encoded).

Maybe you should ask in the addon/script development forum as there are many python addons/scripts that use JSON-RPC, maybe someone can help you there.
OK.

With this code, the slideshow is OK :
Code:
_json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"playlistid": 2, "item": {"file" : "%s"}}, "id": 1}' %(str(_path.encode('utf8')).replace("\\","\\\\")))
Hey guys,
I've been trying to add some new functionality to a project I'm working on (written in PHP5) and after days of reading everything I could find about sending JSON commands I finally had a eureka moment yesterday and can now send/recieve commands via the new WebSocket. The problems I'm having is although I'm able to make it work now and even after reading results from JSONRPC.Introspect I still can't seem to get a bunch of what I would consider 'simple' things to work.

For now, I'm more interested in creating simple buttons that allow you to toggle stuff like Subtitles on/off or "Scan/Update Library" instead of of doing things like listing movies/shows or whatever. Essentially until I'm able to learn this stuff better, I don't care what the response back is since I'm not formatting any of it (in fact, all the Sent/Response stuff will be hidden from the end user anyway).

While testing I tried adding the settings to the advancedsettings.xml to turn off the compact response so I could use it to learn but it made it so that every second or third command would essentially just kill the browser (not crash, but just sit there and not do anything at all).

I guess I'm wondering if anyone knows of a spot where I can read 'real-world' examples of fully written JSON commands. For example, I'm able to scan the video library with: (which works)
Code:
Send:
{"jsonrpc": "2.0", "method": "VideoLibrary.Scan"}
Response:
{"jsonrpc":"2.0","method":"VideoLibrary.OnScanFinished","params":{"data":null,"sender":"xbmc"}}
but trying to scan the audio library, I've tried each of the following: (no error, but doesn't seem to update the library in XBMC)
Code:
Send:
{"jsonrpc": "2.0", "method": "AudioLibrary.Scan"}
Response:
{"jsonrpc":"2.0","method":"AudioLibrary.OnScanFinished","params":{"data":null,"sender":"xbmc"}}
I also tried the following for AudioLibrary: (again, no error, but doesn't seem to actually do anything)
Code:
Send:
{"jsonrpc": "2.0", "method": "AudioLibrary.Scan", "permissions": "UpdateData"}
Response:
{"jsonrpc":"2.0","method":"AudioLibrary.OnScanFinished","params":{"data":null,"sender":"xbmc"}}
I also tried something else, can't remember the exact command but it led me to believe for Audio you have to specify a directory to scan, which if possible I want to avoid and have it scan the entire thing since the end users will obviously have their media in different locations.

Test Environment:
XBMC Nightly: May 28, 2012
Windows 7 Ultimate x64
I have at least one tester on Linux (I believe Ubuntu) to verify the code works for them as well.

I'm not sure what parts of the project code would be helpful with this, but I'm essentially creating arrays like so:
Code:
<?php
$SubtitleOn = array('{"jsonrpc": "2.0", "method": "Player.SetSubtitle", "params": {"playerid": 1, "subtitle" : "on"}, "id": "1"}');
$SubtitleOff = array('{"jsonrpc": "2.0", "method": "Player.SetSubtitle", "params": {"playerid": 1, "subtitle" : "off"}, "id": "1"}');
$ScanVidLib = array('{"jsonrpc": "2.0", "method": "VideoLibrary.Scan"}');
$VidClean = array('{"jsonrpc": "2.0", "method": "VideoLibrary.Clean", "permissions": "RemoveData", "id": "1"}');
// Currently Broken JSON Commands
$VolMute = array('{"jsonrpc": "2.0", "method": "Application.SetMute", "permissions": "ControlPlayback", "id": "1"}');
$VolUp = array();
$VolDown     = array();
$VolMax = array('{"jsonrpc": "2.0", "method": "XBMC.SetVolume", "params": {"SetVolume": 100}, "id": "1"}');
$ScanAudLib = array('{"jsonrpc": "2.0", "method": "AudioLibrary.Scan", "permissions": "UpdateData"}');
?>
And sending them like this:
Code:
<div id="commands"><strong>Video Library</strong>
    <button class='classpanel' name='VidScan' onClick='doSend(<?php echo json_encode($ScanVidLib); ?>)'>Scan</button>
    <button class='classpanel' name='VidClean' onClick='doSend(<?php echo json_encode($VidClean); ?>)'>Clean</button>
</div>

Before this post gets too much longer, clicking a 'broken' command from above (Example: VolMax) displays the Sent/Response like this:
Code:
SENT: {"jsonrpc": "2.0", "method": "XBMC.SetVolume", "params": {"SetVolume": 100}, "id": "1"}
RESPONSE: {"error":{"code":-32601,"message":"Method not found."},"id":"1","jsonrpc":"2.0"}

Any help would be greatly appreciated. (This project is available on GitHub if seeing the actual code might help you guys...)
If you want some examples look https://github.com/frolick/AWX-Eden/blob...ib.xbmc.js line 382 onwards. These are for Eden but you should be able to get the idea. If you don't already, get a restful client for your preferred browser, I find it easier to experiment with the JSONRPC this way. Don't forget using Frodo is you have to set "Content-Type: application/json" in the header.

Volume example:
Code:
{"jsonrpc": "2.0", "method": "Application.SetVolume", "params": { "volume": 95}, "id": 1}
The first thing you should probably read (if you haven't already) is http://wiki.xbmc.org/index.php?title=JSON-RPC_API and the respective page of the version you are using (v4 for Eden and v5 for nightly builds but as you use websockets it's v5 and therefore http://wiki.xbmc.org/index.php?title=JSON-RPC_API/v5). It will probably also help you to read http://www.jsonrpc.org/specification.

(2012-06-01, 20:31)Archigos Wrote: [ -> ]While testing I tried adding the settings to the advancedsettings.xml to turn off the compact response so I could use it to learn but it made it so that every second or third command would essentially just kill the browser (not crash, but just sit there and not do anything at all).
Can you name any specific requests which freeze your browser? The WebSocket support is very new and only a handful of people have really given it a try so far so it's not unlikely that it still contains bugs that need fixing.

(2012-06-01, 20:31)Archigos Wrote: [ -> ]I guess I'm wondering if anyone knows of a spot where I can read 'real-world' examples of fully written JSON commands. For example, I'm able to scan the video library with: (which works)
Code:
Send:
{"jsonrpc": "2.0", "method": "VideoLibrary.Scan"}
Response:
{"jsonrpc":"2.0","method":"VideoLibrary.OnScanFinished","params":{"data":null,"sender":"xbmc"}}
but trying to scan the audio library, I've tried each of the following: (no error, but doesn't seem to update the library in XBMC)
Code:
Send:
{"jsonrpc": "2.0", "method": "AudioLibrary.Scan"}
Response:
{"jsonrpc":"2.0","method":"AudioLibrary.OnScanFinished","params":{"data":null,"sender":"xbmc"}}
I also tried the following for AudioLibrary: (again, no error, but doesn't seem to actually do anything)
Code:
Send:
{"jsonrpc": "2.0", "method": "AudioLibrary.Scan", "permissions": "UpdateData"}
Response:
{"jsonrpc":"2.0","method":"AudioLibrary.OnScanFinished","params":{"data":null,"sender":"xbmc"}}
I also tried something else, can't remember the exact command but it led me to believe for Audio you have to specify a directory to scan, which if possible I want to avoid and have it scan the entire thing since the end users will obviously have their media in different locations.
Concerning your requests to "VideoLibrary.Scan" and "AudioLibrary.Scan": What you posted as a response is actually a notification. The difference between a response and a notification is that a response is sent based on a request whereas a notification is sent based on some event within XBMC itself. The reason you don't get a response to your requests is because you don't provide an "id" in your request (like you do for Player.SetSubtitle" etc). If you don't provide an "id" it will be considered a notification and no response will be sent.

Apart from that both VideoLibrary.Scan and AudioLibrary.Scan should work fine.

(2012-06-01, 20:31)Archigos Wrote: [ -> ]I'm not sure what parts of the project code would be helpful with this, but I'm essentially creating arrays like so:
Code:
<?php
$SubtitleOn = array('{"jsonrpc": "2.0", "method": "Player.SetSubtitle", "params": {"playerid": 1, "subtitle" : "on"}, "id": "1"}');
$SubtitleOff = array('{"jsonrpc": "2.0", "method": "Player.SetSubtitle", "params": {"playerid": 1, "subtitle" : "off"}, "id": "1"}');
$ScanVidLib = array('{"jsonrpc": "2.0", "method": "VideoLibrary.Scan"}');
$VidClean = array('{"jsonrpc": "2.0", "method": "VideoLibrary.Clean", "permissions": "RemoveData", "id": "1"}');
// Currently Broken JSON Commands
$VolMute = array('{"jsonrpc": "2.0", "method": "Application.SetMute", "permissions": "ControlPlayback", "id": "1"}');
$VolUp = array();
$VolDown     = array();
$VolMax = array('{"jsonrpc": "2.0", "method": "XBMC.SetVolume", "params": {"SetVolume": 100}, "id": "1"}');
$ScanAudLib = array('{"jsonrpc": "2.0", "method": "AudioLibrary.Scan", "permissions": "UpdateData"}');
?>
At least when you are still debugging your application you should add an "id" to every one of your requests so that you always get a response. The JSON-RPC 2.0 specification states that if there is no "id" in the request there must not be a response even if it would be an error message.
Player.SetSubtitle looks ok. The VideoLibrary.Scan and AudioLibrary.Scan requests need an "id". The "permissions" property in the other requests is wrong. It's part of XBMC's JSON schema description of the API to give developers an idea whether a specific method just reads data or does something else. In the future it might be used for other things. Application.SetMute needs a "params" object containing a "mute" property with the value true, false or "toggle".

(2012-06-01, 20:31)Archigos Wrote: [ -> ]Before this post gets too much longer, clicking a 'broken' command from above (Example: VolMax) displays the Sent/Response like this:
Code:
SENT: {"jsonrpc": "2.0", "method": "XBMC.SetVolume", "params": {"SetVolume": 100}, "id": "1"}
RESPONSE: {"error":{"code":-32601,"message":"Method not found."},"id":"1","jsonrpc":"2.0"}
As already mentioned by Mizaki there's no XBMC.SetVolume command. It's called Application.SetVolume and its "params" object takes a property named "volume" which can either be a value between 0 and 100 or "increment" or "decrement".

Thank you both for the quick response.

@Mizaki,
I'm going to read over that JavaScript file shortly and get a new restful client as well... I think back when I first started this I tried one and for whatever reason removed it. And for setting the Content-Type I have to check which revision of the files I'm working with, but I think I had it handled, if not thank you for reminding me to add that back in.
Once I get back home and start toying with this again, I imagine your example (along with Montellese's comment) something like these would work for the Volume? (I don't want to give exact percentages).
Code:
{"jsonrpc": "2.0", "method": "Application.SetVolume", "params": { "volume": "increment"}, "id": 1}
{"jsonrpc": "2.0", "method": "Application.SetVolume", "params": { "volume": "decrement"}, "id": 1}

@Montellese,
First, thank you on clarifying some of the terminology I had wrong (see below). I'm still trying to wrap my head around a lot of this. The main reason I'm using websockets right now is that you had posted a link to Websocket.org's Echo Test and I was able to tweak the example they had at the bottom of their page to work. Prior to using this, I was able to get Karl Rixon's XBMC-PHP-RPC to work but couldn't understand enough about how he was doing it for it to work in my case, plus his stuff was pretty much a year old already. Anyway, the base JSON commands I've been attempting so far were pulled from a really long array found in Karl's package and then tweaked as I figured things out to try and get them to work.

For the commands that would freeze the browser (when I set up the advancedsettings.xml) I'll have to try that again, I know at least one of the commands that caused it weren't valid to begin with which is probably what caused it. (I think I was experimenting with trying to take a screenshot or toggle something, but soon removed the command altogether.)

When I gave examples like:
Code:
Send:
{"jsonrpc": "2.0", "method": "VideoLibrary.Scan"}
Response:
{"jsonrpc":"2.0","method":"VideoLibrary.OnScanFinished","params":{"data":null,"sender":"xbmc"}}
I just assumed that "Response" meant response, but "Notification" makes a lot more sense. Since I'm using a modified version of the Echo Test from above, you can easily replicate the 'mis-information' by copy/pasting the commands at the Echo Test page. (Not that any of this stuff really matters at this point).

(2012-06-01, 22:11)Montellese Wrote: [ -> ]At least when you are still debugging your application you should add an "id" to every one of your requests so that you always get a response. The JSON-RPC 2.0 specification states that if there is no "id" in the request there must not be a response even if it would be an error message.
So, "id": "1" should be at the end of each command... I'm guessing it wouldn't hurt to just leave it there even when I'm done since the script outputs everything to a div which I'm hiding in the released version. Also, I think it was in the post, pages back, but I thought the id specified type, like "id": "1" was for video or is this just another area I misunderstood? (The posts were about adding images not in the library into a slideshow or something like that).

(2012-06-01, 22:11)Montellese Wrote: [ -> ]Player.SetSubtitle looks ok. The VideoLibrary.Scan and AudioLibrary.Scan requests need an "id". The "permissions" property in the other requests is wrong.
I'll remove all the permissions and set the id's. So, something like the following should work for Mute then?
Code:
{"jsonrpc": "2.0", "method": "Application.SetMute", "params": {"mute": "toggle"}, "id": "1"}

I can't wait to get home and try some of this new stuff... (with even more reading to be done)... Responding to posts when TeamViewer'd into my laptop from an iPad is a PITA. Smile

Thanks again, I'm sure I'll have more questions later.