User Tools

Site Tools


XBMC Media Center on Linux

Xbox Media Center is an open-source “home theatre PC” project that was originally developed for Microsoft's first Xbox console (hacked to run Linux of course). It has since been ported to run on ordinary desktop Linux and even Windows and Mac.

Standlone Mode

*Challenge*: Get XBMC to run on a separate X-screen, isolated from my desktop environment.

Made with reference to Ubuntu 9.10 (Karmic) for AMD64.

1. X11: Separate X screens

  1. Install nVidia restricted drivers (login and let Karmic offer to do this for you, or install nvidia-glx)
  2. Fix the missing symlink: ln -s /usr/lib/nvidia/ /usr/lib/
  3. sudo service gdm stop to drop to a proper shell
  4. Run sudo nvidia-xconfig -a –separate-x-screens –force-generate to create a new /etc/xorg.conf with both X screens
  5. sudo X -wr to start X with a white region as the background (so you know it's worked!)
  6. DISPLAY=:0.0 xeyes should display on one screen …
  7. DISPLAY=:0.1 xeyes should display on the other …

2. Sound: Pulseaudio at System Start

See also

  1. sudoedit /etc/default/pulseaudio
  2. Start pulseaudio: sudo service pulseaudio start
  3. Add yourself to the pulse-access group, or you'll get “Access denied”: sudo adduser {your-username} pulse-access
  4. Logout and back in to make the new group effective. No really.
    • Check effective groups with id:
      • uid=1000(meermanr) gid=1000(meermanr) groups=4(adm),20(dialout),24(cdrom),46(plugdev),104(lpadmin),115(admin),118(pulse-access),120(sambashare),1000(meermanr)
  5. Try playing something: DISPLAY=: paplay /usr/share/sounds/ubuntu/stereo/system-ready.ogg
    • You need the DISPLAY variable only if you are SSH'd in from another machine; pulseaudio tries to forward the sound over X. Isn't SSH awesome?

3. XBMC: Installing and running

  1. Run DISPLAY=0.1 xbmc –standalone


  • Prevent XBMC capturing the X keyboard and mouse - how will GDM use them?
  • Get GDM to run on *just* DISPLAY=:0.0


  1. You can press “\” to toggle fullscreen mode

Library filename schemes

TV Show file naming conventions

TODO: Configure (or complete for XBMC

Getting AC3 / DTS passthrough to work, despite pulseaudio

While less than ideal, I managed to get AC3 / DTS to pass through pulseaudio, output on SPDIF and decoded by my amp by:

  • Putting pulseaudio's volume controls all on MAX
  • Change pulseaudio's default sampling rate to 48kHz
  • Telling my media player (XBMC) to use the “default” audio output when doing passthough (NOT “iec958” or “spdif”!)

Because the volume is on 100%, the sound data is unchanged by pulseaudio and just “passes through” (so long as no other apps are producing sound, in which case the data gets garbled and my external decoder spits out static until the interfering app shuts-up).

AC3 (Dolby Digital) is signed 16-bit little-endian 2-channel 48kHz PCM data (as far as we want pulseaudio and ALSA to be concerned), but the default pulseaudio sample-rate is 44.1kHz, so when an application attempts to connect to pulseaudio for passthrough pulse rejects the connection because of the sample-rate.

You can change pulseaudio's default sample rate by creating ~/.pulse/daemon.conf like so:

default-sample-rate = 48000

You have to restart pulseaudio for this to take affect (restarting the PC will work as well). I happen to have the pulseaudio-utils package installed which provides the `pacmd` command, and I used it to verify my sample-rates before and after:

# Before reboot
$ pacmd list-sinks | grep sample
	sample spec: s16le 2ch 44100Hz
	sample spec: s16le 2ch 44100Hz

# After reboot
$ pacmd list-sinks | grep sample
	sample spec: s16le 2ch 48000Hz
	sample spec: s16le 2ch 48000Hz

I've read that changing the default sample rate may cause audible crackling and pops when playing sound at the non-default rate, but I've not noticed any after making this change.

Wiimote controls

The default package was unusable when I tried it - tap an arrow key as fast as you like it would register as hit 4+ times: navigating menus was impossible.

So I wrote my own.


  1. XBMC, which comes with Python bindings by default
  2. Python, which comes with Ubuntu by default
  3. The “python-cwiid” package
  4. A wiimote, obviously


#!/usr/bin/env python
def translator(shutdown_event, q_wiimote, q_xbmcclient, log):"Translator started")
	lookup = {
		"EVENT_CONNECTED":		["Notification(Wiimote Connected, Press + and - to disconnect, 3000)"],
		"EVENT_DISCONNECTED":	["Notification(Wiimote Disconnected, Press 1 and 2 to reconnect, 3000)"],
		"BTN_UP":		["Up"],
		"BTN_DOWN":		["Down"],
		"BTN_LEFT":		["Left"],
		"BTN_RIGHT":	["Right"],
		"BTN_A":		["Select"],
		"BTN_B":		["PreviousMenu"],
		"BTN_MINUS":	["OSD", "Fullscreen"],
		"BTN_HOME":		["ActivateWindow(home)"],
		"BTN_PLUS":		["Pause"],
		"BTN_1":		["Info"],
		"BTN_2":		["ContextMenu"],
	while not shutdown_event.is_set():
			event = q_wiimote.get(block=True, timeout=2.0)
			for action in lookup[event]:
		except KeyError:
def xbmcclient(shutdown_event, q, log):
	import xbmc.xbmcclient
	from xbmc.defs import ICON_PATH
	import time"XBMC client started")
	robmote = xbmc.xbmcclient.XBMCClient("Rob's Remote", "icon_wiimote.png")
	robmote.send_notification("Connect Wiimote Now", "Press 1 + 2 on a Wiimote at any time to connect", "icon_wiimote.png")
	# c.f
	while not shutdown_event.is_set():
			action = q.get(block=True, timeout=2.0)
		print action
		if "(" in action:
			robmote.send_action(action, actiontype=xbmc.xbmcclient.ACTION_BUTTON)
import logging
import multiprocessing
import sys
import select
import wiimote
log = multiprocessing.log_to_stderr()
q_wiimote = multiprocessing.JoinableQueue(1)
#q_xbmcclient = multiprocessing.JoinableQueue(1)
q_xbmcclient = multiprocessing.Queue(1)
shutdown_event = multiprocessing.Event()
wiimote = multiprocessing.Process(name="Wiimote", target=wiimote.wiimote_session, args=(shutdown_event, q_wiimote, log))
translator = multiprocessing.Process(name="Translator", target=translator, args=(shutdown_event, q_wiimote, q_xbmcclient, log))
xbmcclient = multiprocessing.Process(name="XBMC client", target=xbmcclient, args=(shutdown_event, q_xbmcclient, log))
xbmcclient.start()[sys.stdin], [], [])	# Block until some input is ready"Signalling shut down")

#!/usr/bin/env python
# Wiimote experiments. Hopefully this'll grow into something I can use with
# wminput (or emulate it to the same affect)
import os
import sys
import time
import cwiid
import Queue	# Just for Queue.Full and Queue.Empty exceptions
def wiimote_session(shutdown_event, q, log):
	# shutdown_event is a multiprocessing.Event which is initially not set. When it
	# is set the wiimote will be disconnected.
	# q is a multiprocessing.JoinableQueue where messages will be put
	# log is a logger to which messages will be written
	def disconnect():
		if wiimote:
			wiimote.rpt_mode = 0
	while not shutdown_event.is_set():
		wiimote = None "Press 1+2 on the Wiimote now..." )
		while not wiimote:
			if shutdown_event.is_set(): return
				wiimote = cwiid.Wiimote()
			except Exception, e:
				log.warning( e )
				log.warning( "(Ignoring previous exception)" )
				time.sleep(0.5) "Successfully connected to Wiimote" )
		wiimote.led = cwiid.LED1_ON | cwiid.LED2_ON | cwiid.LED3_ON | cwiid.LED4_ON
		wiimote.rumble = True
		wiimote.rumble = False
		wiimote.led = cwiid.LED1_ON | cwiid.LED4_ON
		log.debug( wiimote.state )
		wiimote.enable(cwiid.FLAG_MESG_IFC)	# "if changes"
		wiimote.rpt_mode = cwiid.RPT_BTN
		while wiimote:
			messages = wiimote.get_mesg()
			if shutdown_event.is_set():
				wiimote = None
			for mtype, m in messages:
				if mtype == cwiid.MESG_BTN:
					for x in dir(cwiid):
						if not x.startswith("BTN_"): continue
						if eval("cwiid.%s" % x) != m: continue
					if m == cwiid.BTN_PLUS | cwiid.BTN_MINUS: "+ & -, exiting" )
						wiimote = None
				elif mtype == cwiid.MESG_ERROR:
					for x in dir(cwiid):
						if not x.startswith("ERROR_"): continue
						if eval("cwiid.%s" % x) != m: continue
						print x
					for x in dir(cwiid):
						if not x.startswith("MESG_"): continue
						if eval("cwiid.%s" % x) != mtype: continue
						print x
		if shutdown_event.is_set():
def consumer(q):
	print "Starting consumption"
	while True:
		print q.get()
if __name__ == "__main__":
	import logging
	import multiprocessing
	log = multiprocessing.log_to_stderr()
	q = multiprocessing.JoinableQueue(1)
	shutdown_event = multiprocessing.Event()
	wiimote = multiprocessing.Process(name="Wiimote", target=wiimote_session, args=(shutdown_event, q, log))
	consumer = multiprocessing.Process(name="Consumer", target=consumer, args=(q,))
	#print "Signalling shutdown event"


$ ./ 
[INFO/Wiimote] child process calling
[INFO/Wiimote] Press 1+2 on the Wiimote now...
[INFO/Translator] child process calling
[INFO/Translator] Translator started
[INFO/XBMC client] child process calling
[INFO/XBMC client] XBMC client started

# Pressed 1 + 2 ...

[INFO/Wiimote] Successfully connected to Wiimote
Notification(Wiimote Connected, Press + and - to disconnect, 3000)

# Tested some buttons ...

[INFO/Translator] BTN_UP
[INFO/Translator] BTN_DOWN

# Pressed + and - at the same time to turn off Wiimote..

[INFO/Translator] BTN_PLUS
[INFO/Wiimote] + & -, exiting
[INFO/Wiimote] Press 1+2 on the Wiimote now...
Notification(Wiimote Disconnected, Press 1 and 2 to reconnect, 3000)

# Pressed <ENTER> to tell script to exit gracefully

[INFO/MainProcess] Signalling shut down
[INFO/Translator] process shutting down
[INFO/Translator] process exiting with exitcode 0
[INFO/XBMC client] process shutting down
[INFO/XBMC client] process exiting with exitcode 0
No wiimotes found
[WARNING/Wiimote] Error opening wiimote connection
[WARNING/Wiimote] (Ignoring previous exception)
[INFO/Wiimote] process shutting down
[INFO/Wiimote] process exiting with exitcode 0
[INFO/MainProcess] process shutting down

BBC iPlayer + YouTube

1. Install SVN Repo Installer plugin

cd ~/.xbmc/plugins/programs
svn co " Repo Installer"

2. Use SVN Repo Installer plugin

  1. Start XBMC
  2. (Assuming default Project Midnight skin) Home Window → Settings → Skin Settings (side-bar) → Home Windows (side-bar) → Show programs in main menu
  3. Home Window → Programs → Program plugins → SVN Repo Installer → xbmc-addons → plugins → video → IPlayer
  4. Home Window → Programs → Program plugins → SVN Repo Installer → xbmc-addons → plugins → video → YouTube

3. Use iPlayer / YouTube

  1. Home Window → Video → Video plugins → etc

Playing Blurays

unix/xbmc.txt · Last modified: 2011/05/28 14:53 by robm