While now the XBMC is available on most platform: Windows, OS/X (Plex is better IMO, which is based on XBMC, http://www.plexapp.com/), and Linux.
XBMC works fine on ubuntu through ALSA, though I am using JACK (http://jackaudio.org/) for better sound quality, so I have to stop JACK before start XBMC which is quite annoying.
After some research on the web, I decide to implement JACK audio bridge for XBMC, which is quite easy, here is how I did it:
First, get the source code
* http://xbmc.org/development/svn/XBMC already has a flexible structure to support different audio interfaces, under linuxport/XBMC/xbmc/cores/AudioRenderers, there are a bunch of supported interfaces: ALSA, PulseAudio, Windows Direct sound.
Seconds, get the library
JACK comes with C library, it's asynchronus and need some time to learn it, did some research, found out there is a good C++ library at http://x37v.info/jack_cpp/doc/index.html (by Alex Norman, with pretty good documetation and examples, thanks a lot)Now, link them together
To make it simple, I just put all the files from jackcpp under AudioRenderers, then write a simple wrapper to let them talk with each other.There is a NullDirectSound.cpp there, which is a very good example to learn how to write a new interface.
In AudioRendererFactory.cpp, a quick hacky way to use the JACK interface:
--- AudioRendererFactory.cpp (revision 19572)
+++ AudioRendererFactory.cpp (working copy)
@@ -22,6 +22,7 @@
#include "stdafx.h"
#include "AudioRendererFactory.h"
#include "NullDirectSound.h"
+#include "JackDirectSound.h"
#ifdef HAS_PULSEAUDIO
#include "PulseAudioDirectSound.h"
@@ -59,10 +60,14 @@
{
IAudioRenderer* audioSink = NULL;
+//For Jack
+ audioSink = new CJackDirectSound();
+ ReturnOnValidInitialize();
+
Then create JackDirectSound.cpp and JackDirectSound.h (I just copied from NullDirectSound.cpp and NullDirectSound.h)
if you see the diff from JackDirectSound.cpp and NullDirectSound.cpp, you will find out most of them are same except for the change of name, the only logic I added are these lines (full version below):
In Initialize():
I am using blocking interface here, since it's very simple to use.
jackBuffer = new JackCpp::BlockingAudioIO("XBMC.Jack", iChannels, iChannels);
jackBuffer->start();
for(int i = 0; i <>connectToPhysical(i,i);
}
m_uiChannels = iChannels;
In Deinitialize():
if (jackBuffer) {
for(int i = 0; i <>disconnectOutPort(i);
}
jackBuffer->close();
//TODO: Cannot delete jackBuffer, otherwise will crash.
//delete jackBuffer;
}
jackBuffer = 0;
And in AddPackets():
CLog::Log(LOGERROR,"Jack.AddPackets() len=%d, add=%d", len, add);
if (jackBuffer){
short* pSamples = (short*)data;
for (int i=0; i< j =" 0;">write(j, (float) pSamples[i*m_uiChannels + j] / 32768.0);
}
}
}
The logic to convert the data chunks here cause me some trouble, had to do some search and experiments before get the sound right, but before that some result sound were quite interesting.
The last thing in GetDelay():
return m_timePerPacket * (float)m_packetsSent + 0.325 + 0.075;
To be honest, I don't know how to calculate the correct delay value here, this value here was the delay I found out on my machine, just try to play some movie, then try to match the audio to the video, then it's done. (I know, it's very hacky and not the right way, but since the constant value seems to solve my problem perfectly, don't feel pressure to dig into it anymore :) )
Put everything together and make it
Now every thing is ready, you can set it up and make it.I suppose you have enough knowledge about how to compile XBMC on your system, this page http://xbmc.org/wiki/?title=Installing_XBMC_for_Linux has all the information you need.
Modify linuxport/XBMC/xbmc/cores/AudioRenderers/Makefile.in to include the new files (both jack_cpp and my codes)
--- Makefile.in (revision 19572)
+++ Makefile.in (working copy)
@@ -4,11 +4,17 @@
ifeq ($(findstring osx,$(ARCH)), osx)
SRCS = \
+ jackaudioio.cpp \
+ jackblockingaudioio.cpp \
+ JackDirectSound.cpp \
NullDirectSound.cpp \
AudioRendererFactory.cpp \
PortaudioDirectSound.cpp
else
SRCS = \
+ jackaudioio.cpp \
+ jackblockingaudioio.cpp \
+ JackDirectSound.cpp \
NullDirectSound.cpp \
AudioRendererFactory.cpp \
ALSADirectSound.cpp \
And also add jack lib into XBMC/Makefile, search for "-lasound" add "-ljack" the the same line. (Again, this is my hacky and improper way)
Now you are ready to compile it and enjoy the two fantastic software working together!
Download the Patch:
xbmc-jack.tgz
7 comments:
have you submitted this as a patch? or have you considered at least creating a patch for others to try the code? I also use jack and I dont have much choice in the matter as I can't get acceptable sound by any other means.
Also, much of your code was eaten by the html escaping elves.
The Patch can be download from https://sites.google.com/site/yjpark/downloads
That is awesome, thanks. I'll try building it later this afternoon and let you know how it goes.
@ author; if you want this in mainline xbmc, i have created a trac ticket @ http://xbmc.org/trac/ticket/7208
please pop by there :)
@spiff: unfortunately the audio interface has changed since you posted the patch. Could you re-adapt it? - please :/
The hack now can work in ubuntu 9.10 (update following the changes of audio interfaces)
http://yjpark.blogspot.com/2009/11/xbmc-over-jack-revisited.html
Post a Comment