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.
*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.
nvidia-glx
)ln -s /usr/lib/nvidia/libnvidia-cfg.so.185.18.36 /usr/lib/libnvidia-cfg.so.1
sudo service gdm stop
to drop to a proper shellsudo nvidia-xconfig -a –separate-x-screens –force-generate
to create a new /etc/xorg.conf
with both X screenssudo X -wr
to start X with a white region as the background (so you know it's worked!)DISPLAY=:0.0 xeyes
should display on one screen …DISPLAY=:0.1 xeyes
should display on the other …See also http://pulseaudio.org/wiki/SystemWideInstance
sudoedit /etc/default/pulseaudio
PULSEAUDIO_SYSTEM_START=1
DISALLOW_MODULE_LOADING=0
sudo service pulseaudio start
pulse-access
group, or you'll get “Access denied”: sudo adduser {your-username} pulse-access
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)
DISPLAY=: paplay /usr/share/sounds/ubuntu/stereo/system-ready.ogg
DISPLAY
variable only if you are SSH'd in from another machine; pulseaudio tries to forward the sound over X. Isn't SSH awesome?DISPLAY=0.1 xbmc –standalone
\
” to toggle fullscreen modeTV Show file naming conventions
TODO: Configure tvrenamer.pl
(or complete tvrenamer.py
) for XBMC
http://ubuntuforums.org/showpost.php?p=7560563&postcount=3
While less than ideal, I managed to get AC3 / DTS to pass through pulseaudio, output on SPDIF and decoded by my amp by:
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.
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.
robmote.py
#!/usr/bin/env python def translator(shutdown_event, q_wiimote, q_xbmcclient, log): log.info("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(): try: event = q_wiimote.get(block=True, timeout=2.0) except: continue log.info(event) try: for action in lookup[event]: q_xbmcclient.put(action) except KeyError: pass q_wiimote.task_done() def xbmcclient(shutdown_event, q, log): import xbmc.xbmcclient from xbmc.defs import ICON_PATH import time log.info("XBMC client started") robmote = xbmc.xbmcclient.XBMCClient("Rob's Remote", "icon_wiimote.png") robmote.connect() robmote.send_notification("Connect Wiimote Now", "Press 1 + 2 on a Wiimote at any time to connect", "icon_wiimote.png") #time.sleep(3) # c.f http://xbmc.org/wiki/?title=List_of_Built_In_Functions #robmote.send_action("ActivateWindow(home)") while not shutdown_event.is_set(): try: action = q.get(block=True, timeout=2.0) except: continue print action if "(" in action: robmote.send_action(action) else: robmote.send_action(action, actiontype=xbmc.xbmcclient.ACTION_BUTTON) #q.task_done() robmote.close() import logging import multiprocessing import sys import select import wiimote log = multiprocessing.log_to_stderr() log.setLevel(logging.INFO) 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)) wiimote.start() translator.start() xbmcclient.start() select.select([sys.stdin], [], []) # Block until some input is ready log.info("Signalling shut down") shutdown_event.set() wiimote.join() translator.join() xbmcclient.join()
wiimote.py
#!/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(): q.put("EVENT_DISCONNECTED") if wiimote: wiimote.disable(cwiid.FLAG_MESG_IFC) wiimote.rpt_mode = 0 wiimote.close() q.join() while not shutdown_event.is_set(): wiimote = None log.info( "Press 1+2 on the Wiimote now..." ) while not wiimote: if shutdown_event.is_set(): return try: wiimote = cwiid.Wiimote() except Exception, e: log.warning( e ) log.warning( "(Ignoring previous exception)" ) time.sleep(0.5) log.info( "Successfully connected to Wiimote" ) q.put("EVENT_CONNECTED") wiimote.led = cwiid.LED1_ON | cwiid.LED2_ON | cwiid.LED3_ON | cwiid.LED4_ON wiimote.rumble = True time.sleep(0.4) wiimote.rumble = False wiimote.led = cwiid.LED1_ON | cwiid.LED4_ON q.join() 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(): disconnect() wiimote = None continue 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 q.put(x) q.join() break if m == cwiid.BTN_PLUS | cwiid.BTN_MINUS: log.info( "+ & -, exiting" ) disconnect() 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 return else: for x in dir(cwiid): if not x.startswith("MESG_"): continue if eval("cwiid.%s" % x) != mtype: continue print x break if shutdown_event.is_set(): return def consumer(q): print "Starting consumption" while True: print q.get() sys.stdout.flush() q.task_done() if __name__ == "__main__": import logging import multiprocessing log = multiprocessing.log_to_stderr() log.setLevel(logging.INFO) 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,)) wiimote.start() consumer.start() #time.sleep(10) #print "Signalling shutdown event" #shutdown_event.set() wiimote.join() consumer.terminate()
meermanr@ikari:/store/projects/wiimote $ ./robmote.py [INFO/Wiimote] child process calling self.run() [INFO/Wiimote] Press 1+2 on the Wiimote now... [INFO/Translator] child process calling self.run() [INFO/Translator] Translator started [INFO/XBMC client] child process calling self.run() [INFO/XBMC client] XBMC client started # Pressed 1 + 2 ... [INFO/Wiimote] Successfully connected to Wiimote [INFO/Translator] EVENT_CONNECTED Notification(Wiimote Connected, Press + and - to disconnect, 3000) # Tested some buttons ... [INFO/Translator] BTN_UP Up [INFO/Translator] BTN_DOWN Down # Pressed + and - at the same time to turn off Wiimote.. [INFO/Translator] BTN_PLUS Pause [INFO/Wiimote] + & -, exiting [INFO/Translator] EVENT_DISCONNECTED [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
cd ~/.xbmc/plugins/programs svn co "http://xbmc-addons.googlecode.com/svn/trunk/plugins/programs/SVN Repo Installer"