XBMC’s JSON-RPC API – REALLY Pausing a video

In an earlier post, “Calling XBMC’s JSON-RPC API using Python’s requests library – Pause a video“, I showed an example of pausing the actively playing file using the XBMC JSON-RPC API’s Player.PlayPause method. The problem with this method, as you could probably already tell from its name, is that it acts like a toggle – if the video is playing, it pauses it. If it is already paused, it is unpaused. Great for remote controls, but useless for anything else.

It took quite a bit of searching to figure out how to only pause a file if it is currently busy playing. The answer is to use the Player.GetProperties method to retrieve the “speed” of the currently playing file, which tells us if the file is playing or not. So, to pause we need 3 calls to the API:

– Player.GetActivePlayers to get the actively playing file’s “playerid”
– Player.GetProperties passing the playerid from the response of Player.GetActivePlayers to get the “speed” which should tell us if the file is paused or not
– Player.PlayPause called only if the speed returned is not 0

The code:

import requests
import json
import urllib

#Required header for XBMC JSON-RPC calls, otherwise you'll get a
#415 HTTP response code - Unsupported media type
headers = {'content-type': 'application/json'}

#Host name where XBMC is running, leave as localhost if on this PC
#Make sure "Allow control of XBMC via HTTP" is set to ON in Settings ->
#Services -> Webserver
xbmc_host = 'localhost'

#Configured in Settings -> Services -> Webserver -> Port
xbmc_port = 8888

#Base URL of the json RPC calls. For GET calls we append a "request" URI
#parameter. For POSTs, we add the payload as JSON the the HTTP request body
xbmc_json_rpc_url = "http://" + xbmc_host + ":" + str(xbmc_port) + "/jsonrpc"

#Payload for the method to get the currently playing / paused video or audio
payload = {"jsonrpc": "2.0", "method": "Player.GetActivePlayers", "id": 1}
url_param = urllib.urlencode({'request': json.dumps(payload)})

response = requests.get(xbmc_json_rpc_url + '?' + url_param,
                        headers=headers)

#response.text will look like this if something is playing
#{"id":1,"jsonrpc":"2.0","result":[{"playerid":1,"type":"video"}]}
#and if nothing is playing:
#{"id":1,"jsonrpc":"2.0","result":[]}

data = json.loads(response.text)
#result is an empty list if nothing is playing or paused.
if data['result']:
    #We need the specific "playerid" of the currently playing file in order
    #to pause it
    player_id = data['result'][0]["playerid"]
    
    payload = {"jsonrpc": "2.0", "method": "Player.GetProperties",
               "params": { "playerid": player_id, "properties" : ["speed"] }, "id": 1}
    url_param = urllib.urlencode({'request': json.dumps(payload)})
    response = requests.get(xbmc_json_rpc_url + '?' + url_param,
                        headers=headers)
                        
    data = json.loads(response.text)         

    if data["result"]["speed"]:
        payload = {"jsonrpc": "2.0", "method": "Player.PlayPause",
                   "params": { "playerid": player_id }, "id": 1}
        response = requests.post(xbmc_json_rpc_url, data=json.dumps(payload),
                                 headers=headers)

        #response.text will look like this if we're successful:
        #{"id":1,"jsonrpc":"2.0","result":{"speed":0}}

Raspbmc – Control XBMC with your TV remote using HDMI-CEC

Edit: Raspbmc RC4 now has CEC enabled out of the box – No need to enable the XBMC web server. It uses the newer libCEC which has significantly better support for different manufacturer CEC-based implementations, so chances are it will work just fine with your CEC-enabled TV.

CEC is a specification that allows control of CEC-enabled devices that are attached through HDMI.

Raspbmc has included a basic implementation of CEC in version RC3, meaning you can now control your Raspberry Pi installation from your CEC-enabled TV remote (well in theory, anyway).

You’ll need a CEC-enabled TV or amplifier that is connectioned to your Raspberry Pi via the HDMI connector.  Not all CEC-enabled devices are created equally, though, and might support a different subset of the specification. This means that CEC on your device might not interface with XBMC at all, or some of the remote buttons won’t be mapped correctly. On the Samsung Anynet+ (Samsung’s version of CEC) TV I tested on, the arrow keys and enter was working, but pause, play, stop etc. wasn’t. Your mileage may vary.

Support for CEC was only included in Raspbmc from version RC3, but it is not present in the normal XBMC build. It is enabled by default, but in order for it to work, you need to activate XBMC’s web server:

  • Go to Settings -> Network -> Services
  • Set “Allow control of XBMC via HTTP” to on.
  • Set the username to “xbmc” and leave the password blank
  • Make sure the port is set to 8080

Enabling CEC control of XBMC on your TV should be simple – select the source input and select the XBMC CEC device input (The TV should automatically pick up XBMC as a CEC device).

Reducing lag while watching HD videos on Raspbmc / Raspberry Pi

I’ve noticed some lag while playing HD movies on my Raspberry Pi with Raspbmc from my SMB shares. I’ve found an easy way to fix this by reducing video refresh rate during video playback (forum topic here).

In XBMC, go to Settings -> System Settings -> Video output -> Refresh rate. (this seems to be a Raspbmc-specific setting, so you won’t find it in XBMC)

Set this number to a lower setting. The ideal setting would be the highest refresh rate that still allows all or most of your videos to play without lag, so that you have the highest quality video output possible.  So you’ll need to do a bit of experimentation with your setup to find the best refresh rate setting.