PND4

/dev/notes

JSON-RPC + Kodi = BFFs

The can of worms.

The other night I decided to do the long-overdue update of my Gentoo install on my netbook which serves as my XBMC machine. As expected, something along the way broke and XBMC's dependency, ffmpeg, failed to build. After a long struggle, I gave up on the XBMC ebuild and went with XBMC's successor, Kodi. Making haste, I neglected to enable any of Kodi's optional USE-flags. The result: everything perfect Kodi-side (faster actually), but my various remote-control browser-addons, mobile apps, and scripts were made useless.

Meet Kodi's fwiend, JSON-RPC

For months now I've been using a script called xbmc-play. It was simple to use, and lightweight. Problem is that, like most XBMC/Kodi remotes, the underlying mechanics that handle the communication required the webserver feature on the Kodi machine. Since I know a fair amount about scripting and very little of building extensions for browsers and Android apps, scripting became the first part of this journey to regain remoting ability.

In first discovering the lack of a webserver, running netstat -tuanp confirmed no process was listening on the defaut port 8080. The listing did reveal that after enabling "Allow programs on other systems to control Kodi" it listens on port 9090. And a quick google of Kodi's relation to this port will tell you that the JSON-RPC protocol is what's understood on Kodi's end.

First Impression

Looking over the JSON-RPC API articles at the Kodi Wiki and it's official documentation you can get ideas about the syntax of these 'requests' the commands have to make and go from there.

Prior experience manually interacting over TCP/IP came in handy. I was quickly able to test some prototype requests with Kodi using the wiki-suggested telnet tool. Ultimately, I chose to work with netcat as it seemed more fitting for use in the resulting script that follows:

(kodi-play.sh) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/bin/bash

## YouTube Kodi Script [http://github.com/pnd4/kodi-play] 
#by pnd4 
#
# - Portions from "YouTube XBMC Script" by Tom Laermans [tomlaermans.net]. 
#   This script is (also) released into the public domain.
# - Description: Uses Kodi's native JSON-RPC to play YouTube content remotely
#   without need for the webserver.
# - Requires: netcat (tested with GNU Netcat)
# - Usage: kodi-play < URL | YouTube-ID >
# -    ex: kodi-play hABj_mrP-no

## Configure Kodi's RPC details here
KODI_HOST=gen2
KODI_PORT=9090

## Don't touch anything under here

REGEX="^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*"

ID=$1

if [ "$ID" == "" ];
then
  echo "Syntax $0 <id|url>"
  exit
fi

if [[ $ID =~ $REGEX ]]; then
  ID=${BASH_REMATCH[7]}
fi

# Sends our JSON-RPC request to Kodi, and closes the connection.
function jrpc_req {
    echo -n "$1" EOF | nc -c $KODI_HOST $KODI_PORT;
}

echo -n "Opening video id $ID on $KODI_HOST ... "


jrpc_req '{"jsonrpc": "2.0", 
           "method": "Playlist.Clear", 
           "params":{"playlistid":1}, 
           "id": 0}';

jrpc_req '{"jsonrpc": "2.0", 
           "method": 
           "Playlist.Add", 
           "params":{"playlistid":1, 
           "item" :{ "file" : "plugin://plugin.video.youtube/?action=play_video&videoid='$ID'"}}, 
           "id": 0}';

jrpc_req '{"jsonrpc": "2.0", 
           "method": 
           "Player.Open", 
           "params":{"item":{"playlistid":1, "position" : 0}}, 
           "id": 0}';

echo "Done."

What's Next

Having got to dabble into communicating with Kodi over JSON-RPC and being with met less trouble than success. I'm thinking about pursuing a desktop application or at least framework for controlling Kodi/XBMC. It would certainly fulfull my need, and maybe help someone else looking for remote-control without the need for a excess bloat services like a webserver or unnecessary consumption of resources client-side from yet another browser-addon.

With the advent of compact low-powered embedded systems, people seem forget to leverage the power of older systems largely in part due to resource limitations. My netbook, for instance, at most can have 2GB of RAM. Modern machines come with at least 4GB these days, but modern applications like Chrome are quick to claim it. If we choose to design our systems and their appilcations intelligently life won't necessarily be over for such devices like my netbook and won't be for some time as long as we remain resourceful as users and continue to keep modularity in mind as developers.