aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'media-tv/xbmc/files/xbmc-10.1~beta1-jack.patch.bkp')
-rw-r--r--media-tv/xbmc/files/xbmc-10.1~beta1-jack.patch.bkp1738
1 files changed, 1738 insertions, 0 deletions
diff --git a/media-tv/xbmc/files/xbmc-10.1~beta1-jack.patch.bkp b/media-tv/xbmc/files/xbmc-10.1~beta1-jack.patch.bkp
new file mode 100644
index 0000000..23933a9
--- /dev/null
+++ b/media-tv/xbmc/files/xbmc-10.1~beta1-jack.patch.bkp
@@ -0,0 +1,1738 @@
+Index: xbmc/cores/AudioRenderers/jackblockingaudioio.hpp
+===================================================================
+--- xbmc/cores/AudioRenderers/jackblockingaudioio.hpp (revision 0)
++++ xbmc/cores/AudioRenderers/jackblockingaudioio.hpp (revision 1806)
+@@ -0,0 +1,176 @@
++//C++ Classes that wrap JACK
++//Copyright 2007 Alex Norman
++//
++//This file is part of JACKC++.
++//
++//JACKC++ is free software: you can redistribute it and/or modify
++//it under the terms of the GNU General Public License as published by
++//the Free Software Foundation, either version 3 of the License, or
++//(at your option) any later version.
++//
++//JACKC++ is distributed in the hope that it will be useful,
++//but WITHOUT ANY WARRANTY; without even the implied warranty of
++//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++//GNU General Public License for more details.
++//
++//You should have received a copy of the GNU General Public License
++//along with JACKC++. If not, see <http://www.gnu.org/licenses/>.
++
++#ifndef JACK_BLOCKING_AUDIO_IO_HPP
++#define JACK_BLOCKING_AUDIO_IO_HPP
++
++#include "jackaudioio.hpp"
++#include "jackringbuffer.hpp"
++
++namespace JackCpp {
++
++/**
++@class BlockingAudioIO
++
++@brief This is an class that provides a blocking read/write interface for Jack.
++
++This class has read/write methods that allow users to write audio to and read
++audio from a Jack client.
++
++@author Alex Norman
++
++*/
++ class BlockingAudioIO : public AudioIO {
++ public:
++ /**
++ @brief The Constructor
++ \param name string indicating the name of the jack client to create
++ \param inChans an unsigned integer indicating the number of default input ports to create
++ \param outChans an unsigned integer indicating the number of default output ports to create
++ \param inBufSize the size of the buffer that the jack callback fills for us to read with read
++ \param outBufSize the size of the buffer that we write to and the jack callback reads from
++ \param startServer a boolean indicating whether to start a jack server if one isn't already running
++ \sa AudioIO::AudioIO
++ */
++ BlockingAudioIO(std::string name,
++ unsigned int inChans = 2, unsigned int outChans = 2,
++ unsigned int inBufSize = 0, unsigned int outBufSize = 0,
++#ifdef __APPLE__
++ bool startServer = false)
++#else
++ bool startServer = true)
++#endif
++ throw(std::runtime_error);
++ virtual ~BlockingAudioIO();
++
++ /**
++ @brief Write to an output buffer
++
++ Writes val to the output[channel] (if it exists). If
++ output[channel] does not exist is silently fails otherwise it
++ sleeps until it can write output[channel]
++
++ \param channel the output chanel to write to
++ \param val the value to write to the channel
++ \sa tryWrite(unsigned int channel, jack_default_audio_sample_t val)
++ */
++ void write(unsigned int channel, jack_default_audio_sample_t val);
++
++ /**
++ @brief Try to write to an output buffer
++
++ Trys to write to output[channel] (if it exists). If it succeeds it
++ returns true. If it fails, because the buffer is full, it returns
++ false.
++
++ \param channel the output chanel to write to
++ \param val the value to write to the channel
++ \return true if it can write, false if it cannot
++ \sa write(unsigned int channel, jack_default_audio_sample_t val)
++ */
++ bool tryWrite(unsigned int channel, jack_default_audio_sample_t val);
++
++ /**
++ @brief Read from an input buffer.
++
++ Reads from input[channel] if it exists. If there is no input to
++ read it sleeps until there is.
++
++ \param channel the input chanel to read from
++ \return the value read from the input channel [will be zero if the channel does not exist]
++ \sa tryRead(unsigned int channel, jack_default_audio_sample_t &val)
++ */
++ jack_default_audio_sample_t read(unsigned int channel);
++
++ /**
++ @brief Try to read from to an input buffer
++
++ Trys to read from input[channel] (if it exists). If it succeeds it
++ returns true. If it fails, because the buffer is empty, it returns
++ false.
++
++ \param channel the output chanel to read from
++ \param val the value to read into (basically a return value)
++ \return true if it can read, false if it cannot
++ \sa read(unsigned int channel)
++ */
++ bool tryRead(unsigned int channel, jack_default_audio_sample_t &val);
++
++ //XXX reserve exists but is basically useless as you cannot
++ //add ports while the client is active
++ ///This method is useless at the moment.
++ virtual void reserveOutPorts(unsigned int num)
++ throw(std::runtime_error);
++ ///This method is useless at the moment.
++ virtual void reserveInPorts(unsigned int num)
++ throw(std::runtime_error);
++
++ /**
++ @brief Add an input port to our client
++
++ Unlike AudioIO, this currently cannot be called while the client is running.
++
++ \param name string the name of the port to add
++ \return the number of total input ports
++ \sa AudioIO::addInPort(std::string name)
++ */
++ virtual unsigned int addInPort(std::string name)
++ throw(std::runtime_error);
++ /**
++ @brief Add an output port to our client
++
++ Unlike AudioIO, this currently cannot be called while the client is running.
++
++ \param name string the name of the port to add
++ \return the number of total output ports
++ \sa AudioIO::addOutPort(std::string name)
++ */
++ virtual unsigned int addOutPort(std::string name)
++ throw(std::runtime_error);
++
++ protected:
++ /**
++ @brief This is the callback that processes our buffers.
++
++ This method takes the buffers we write to with "write" and writes
++ them out to the Jack bus. It also takes audio from the Jack bus
++ and uses that to fill the input buffers that we read from.
++
++ \param nframes the number frames to process
++ \param inBufs a vector of audio buffers
++ \param outBufs a vector of audio buffers
++ \return the actual number of frames processed
++ */
++ virtual int audioCallback(jack_nframes_t nframes,
++ std::vector<jack_default_audio_sample_t *> inBufs,
++ std::vector<jack_default_audio_sample_t *> outBufs);
++ private:
++ std::vector<RingBuffer<jack_default_audio_sample_t> *> mUserOutBuff;
++ std::vector<RingBuffer<jack_default_audio_sample_t> *> mUserInBuff;
++
++ //this is the size of the ring buffers that we alloc
++ const unsigned int mOutputBufferMaxSize;
++ const unsigned int mInputBufferMaxSize;
++ //this is the amount of free space we leave in the ring buffers
++ //this can decrease so that we'll have more latency but fewer glitches
++ unsigned int mOutputBufferFreeSize;
++ unsigned int mInputBufferFreeSize;
++ };
++}
++#endif
++
+Index: xbmc/cores/AudioRenderers/Makefile.in
+===================================================================
+--- xbmc/cores/AudioRenderers/Makefile.in (revision 1805)
++++ xbmc/cores/AudioRenderers/Makefile.in (revision 1806)
+@@ -4,11 +4,17 @@
+
+ ifeq ($(findstring osx,$(ARCH)), osx)
+ SRCS = \
++ jackaudioio.cpp \
++ jackblockingaudioio.cpp \
++ JackDirectSound.cpp \
+ NullDirectSound.cpp \
+ AudioRendererFactory.cpp \
+ CoreAudioRenderer.cpp
+ else
+ SRCS = \
++ jackaudioio.cpp \
++ jackblockingaudioio.cpp \
++ JackDirectSound.cpp \
+ NullDirectSound.cpp \
+ AudioRendererFactory.cpp \
+ ALSADirectSound.cpp \
+Index: xbmc/cores/AudioRenderers/JackDirectSound.cpp
+===================================================================
+--- xbmc/cores/AudioRenderers/JackDirectSound.cpp (revision 0)
++++ xbmc/cores/AudioRenderers/JackDirectSound.cpp (revision 1806)
+@@ -0,0 +1,243 @@
++/*
++ * Copyright (C) 2005-2008 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include "JackDirectSound.h"
++#include "AudioContext.h"
++#include "Application.h"
++#include "utils/log.h"
++#include "utils/TimeUtils.h"
++
++#define BUFFER CHUNKLEN * 20
++#define CHUNKLEN 512
++
++
++void CJackDirectSound::DoWork()
++{
++
++}
++
++//////////////////////////////////////////////////////////////////////
++// Construction/Destruction
++//////////////////////////////////////////////////////////////////////
++//***********************************************************************************************
++CJackDirectSound::CJackDirectSound()
++{
++ jackBuffer = 0;
++}
++bool CJackDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec, bool bIsMusic, bool bPassthrough)
++{
++ CLog::Log(LOGERROR,"Jack.Initialize() - Channels: %i - SampleRate: %i - SampleBit: %i - Resample %s - Codec %s - IsMusic %s - IsPassthrough %s", iChannels, uiSamplesPerSec, uiBitsPerSample, bResample ? "true" : "false", strAudioCodec, bIsMusic ? "true" : "false", bPassthrough ? "true" : "false");
++ if (iChannels == 0)
++ iChannels = 2;
++
++ bool bAudioOnAllSpeakers(false);
++ g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
++ g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
++
++
++ jackBuffer = new JackCpp::BlockingAudioIO("XBMC.Jack", iChannels, iChannels);
++ jackBuffer->start();
++ for(int i = 0; i < iChannels; i++){
++ jackBuffer->connectToPhysical(i,i);
++ }
++ m_uiChannels = iChannels;
++
++ //g_application.m_guiDialogKaiToast.QueueNotification("Failed to initialize audio device", "Check your audiosettings"
++
++ m_timePerPacket = 1.0f / (float)(iChannels*(uiBitsPerSample/8) * uiSamplesPerSec);
++ m_packetsSent = 0;
++ m_paused = 0;
++ m_lastUpdate = CTimeUtils::GetTimeMS();
++ return true;
++}
++
++//***********************************************************************************************
++CJackDirectSound::~CJackDirectSound()
++{
++ Deinitialize();
++}
++
++
++//***********************************************************************************************
++bool CJackDirectSound::Deinitialize()
++{
++ CLog::Log(LOGERROR,"Jack.Deinitialize");
++ if (jackBuffer) {
++ for(int i = 0; i < m_uiChannels; i++){
++ jackBuffer->disconnectOutPort(i);
++ }
++ jackBuffer->close();
++ //TODO: Cannot delete jackBuffer, otherwise will crash.
++ //delete jackBuffer;
++ }
++ jackBuffer = 0;
++
++ g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
++ return true;
++}
++
++void CJackDirectSound::Flush()
++{
++ m_lastUpdate = CTimeUtils::GetTimeMS();
++ m_packetsSent = 0;
++ Pause();
++}
++
++//***********************************************************************************************
++bool CJackDirectSound::Pause()
++{
++ m_paused = true;
++ return true;
++}
++
++//***********************************************************************************************
++bool CJackDirectSound::Resume()
++{
++ m_paused = false;
++ return true;
++}
++
++//***********************************************************************************************
++bool CJackDirectSound::Stop()
++{
++ Flush();
++ return true;
++}
++
++//***********************************************************************************************
++long CJackDirectSound::GetCurrentVolume() const
++{
++ return m_nCurrentVolume;
++}
++
++//***********************************************************************************************
++void CJackDirectSound::Mute(bool bMute)
++{
++}
++
++//***********************************************************************************************
++bool CJackDirectSound::SetCurrentVolume(long nVolume)
++{
++ m_nCurrentVolume = nVolume;
++ return true;
++}
++
++
++//***********************************************************************************************
++unsigned int CJackDirectSound::GetSpace()
++{
++ Update();
++
++ if(BUFFER > m_packetsSent)
++ return (int)BUFFER - m_packetsSent;
++ else
++ return 0;
++}
++
++//***********************************************************************************************
++unsigned int CJackDirectSound::AddPackets(const void* data, unsigned int len)
++{
++ if (m_paused)
++ return 0;
++ Update();
++
++ int add = ( len / GetChunkLen() ) * GetChunkLen();
++ m_packetsSent += add;
++
++ CLog::Log(LOGERROR,"Jack.AddPackets() len=%d, add=%d", len, add);
++
++ if (jackBuffer){
++ short* pSamples = (short*)data;
++ for (int i=0; i< add/sizeof(short)/m_uiChannels; i++){
++ for(unsigned int j = 0; j < m_uiChannels; j++){
++ jackBuffer->write(j, (float) pSamples[i*m_uiChannels + j] / 32768.0);
++ }
++ }
++ }
++
++ return add;
++}
++
++//***********************************************************************************************
++float CJackDirectSound::GetDelay()
++{
++ Update();
++
++ return m_timePerPacket * (float)m_packetsSent + 0.4;
++}
++
++float CJackDirectSound::GetCacheTime()
++{
++ return GetDelay();
++}
++
++//***********************************************************************************************
++unsigned int CJackDirectSound::GetChunkLen()
++{
++ return (int)CHUNKLEN;
++}
++//***********************************************************************************************
++int CJackDirectSound::SetPlaySpeed(int iSpeed)
++{
++ return 0;
++}
++
++void CJackDirectSound::RegisterAudioCallback(IAudioCallback *pCallback)
++{
++}
++
++void CJackDirectSound::UnRegisterAudioCallback()
++{
++}
++
++void CJackDirectSound::WaitCompletion()
++{
++ while(m_packetsSent > 0)
++ Update();
++}
++
++void CJackDirectSound::SwitchChannels(int iAudioStream, bool bAudioOnAllSpeakers)
++{
++ return ;
++}
++
++void CJackDirectSound::Update()
++{
++ long currentTime = CTimeUtils::GetTimeMS();
++ long deltaTime = (currentTime - m_lastUpdate);
++
++ if (m_paused)
++ {
++ m_lastUpdate += deltaTime;
++ return;
++ }
++
++ double d = (double)deltaTime / 1000.0f;
++
++ if (currentTime != m_lastUpdate)
++ {
++ double i = (d / (double)m_timePerPacket);
++ m_packetsSent -= (long)i;
++ if (m_packetsSent < 0)
++ m_packetsSent = 0;
++ m_lastUpdate = currentTime;
++ }
++}
+Index: xbmc/cores/AudioRenderers/AudioRendererFactory.cpp
+===================================================================
+--- xbmc/cores/AudioRenderers/AudioRendererFactory.cpp (revision 1805)
++++ xbmc/cores/AudioRenderers/AudioRendererFactory.cpp (revision 1806)
+@@ -24,6 +24,7 @@
+ #include "GUISettings.h"
+ #include "log.h"
+ #include "NullDirectSound.h"
++#include "JackDirectSound.h"
+
+ #ifdef HAS_PULSEAUDIO
+ #include "PulseAudioDirectSound.h"
+@@ -132,6 +133,10 @@
+
+ device = deviceString;
+
++//For Jack
++ audioSink = new CJackDirectSound();
++ ReturnOnValidInitialize();
++
+ /* First pass creation */
+ #ifdef HAS_PULSEAUDIO
+ audioSink = new CPulseAudioDirectSound();
+Index: xbmc/cores/AudioRenderers/JackDirectSound.h
+===================================================================
+--- xbmc/cores/AudioRenderers/JackDirectSound.h (revision 0)
++++ xbmc/cores/AudioRenderers/JackDirectSound.h (revision 1806)
+@@ -0,0 +1,79 @@
++/*
++ * Copyright (C) 2005-2008 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#ifndef __JACK_DIRECT_SOUND_H__
++#define __JACK_DIRECT_SOUND_H__
++
++#if _MSC_VER > 1000
++#pragma once
++#endif // _MSC_VER > 1000
++
++#include "IAudioRenderer.h"
++#include "IAudioCallback.h"
++
++#include "jackblockingaudioio.hpp"
++
++extern void RegisterAudioCallback(IAudioCallback* pCallback);
++extern void UnRegisterAudioCallback();
++
++class CJackDirectSound : public IAudioRenderer
++{
++public:
++ virtual void UnRegisterAudioCallback();
++ virtual void RegisterAudioCallback(IAudioCallback* pCallback);
++ virtual unsigned int GetChunkLen();
++ virtual float GetDelay();
++ virtual float GetCacheTime();
++ CJackDirectSound();
++ virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, const char* strAudioCodec = "", bool bIsMusic=false, bool bPassthrough = false);
++ virtual ~CJackDirectSound();
++
++ virtual unsigned int AddPackets(const void* data, unsigned int len);
++ virtual unsigned int GetSpace();
++ virtual bool Deinitialize();
++ virtual bool Pause();
++ virtual bool Stop();
++ virtual bool Resume();
++
++ virtual long GetCurrentVolume() const;
++ virtual void Mute(bool bMute);
++ virtual bool SetCurrentVolume(long nVolume);
++ virtual int SetPlaySpeed(int iSpeed);
++ virtual void WaitCompletion();
++ virtual void DoWork();
++ virtual void SwitchChannels(int iAudioStream, bool bAudioOnAllSpeakers);
++
++ virtual void Flush();
++private:
++ long m_nCurrentVolume;
++
++ float m_timePerPacket;
++ int m_packetsSent;
++ bool m_paused;
++ long m_lastUpdate;
++
++ int m_uiChannels;
++ JackCpp::BlockingAudioIO* jackBuffer;
++
++ void Update();
++};
++
++#endif
+Index: xbmc/cores/AudioRenderers/jackaudioio.cpp
+===================================================================
+--- xbmc/cores/AudioRenderers/jackaudioio.cpp (revision 0)
++++ xbmc/cores/AudioRenderers/jackaudioio.cpp (revision 1806)
+@@ -0,0 +1,475 @@
++//C++ Classes that wrap JACK
++//Copyright 2007 Alex Norman
++//
++//This file is part of JACKC++.
++//
++//JACKC++ is free software: you can redistribute it and/or modify
++//it under the terms of the GNU General Public License as published by
++//the Free Software Foundation, either version 3 of the License, or
++//(at your option) any later version.
++//
++//JACKC++ is distributed in the hope that it will be useful,
++//but WITHOUT ANY WARRANTY; without even the implied warranty of
++//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++//GNU General Public License for more details.
++//
++//You should have received a copy of the GNU General Public License
++//along with JACKC++. If not, see <http://www.gnu.org/licenses/>.
++
++#include "jackaudioio.hpp"
++#include <iostream>
++#include <errno.h>
++#include <sstream>
++#include <algorithm>
++
++template <typename T>
++std::string ToString(T aValue){
++ std::stringstream ss;
++ ss << aValue;
++ return ss.str();
++}
++
++/* callback for jack's error messages */
++static void error_callback (const char *msg) {
++ std::cerr << "Jack:" << msg << std::endl;
++ std::cerr.flush();
++}
++
++static void shutdown_callback (void *arg) {
++ return ((JackCpp::AudioIO *)arg)->jackShutdownCallback();
++}
++
++void JackCpp::AudioIO::jackShutdownCallback(){
++ std::cerr << std::endl << "jack has shutdown" << std::endl;
++}
++
++int JackCpp::AudioIO::jackProcessCallback(jack_nframes_t nframes, void *arg){
++ JackCpp::AudioIO* callbackjackobject = (AudioIO * )arg;
++ return callbackjackobject->jackToClassAudioCallback(nframes);
++}
++
++int JackCpp::AudioIO::jackToClassAudioCallback(jack_nframes_t nframes){
++ //read in commands
++ while(mCmdBuffer.getReadSpace() > 0){
++ cmd_t cmd;
++ mCmdBuffer.read(cmd);
++ switch(cmd){
++ case add_in_port:
++ //we will have tested that we have this capacity, so we resize the buffer
++ //to include the new port
++ mJackInBuf.resize(mJackInBuf.size() + 1);
++ mNumInputPorts++;
++ break;
++ case add_out_port:
++ //we will have tested that we have this capacity, so we resize the buffer
++ //to include the new port
++ mJackOutBuf.resize(mJackOutBuf.size() + 1);
++ mNumOutputPorts++;
++ break;
++ }
++ }
++
++ //get the input and output buffers
++ for(unsigned int i = 0; i < mNumInputPorts; i++)
++ mJackInBuf[i] = (jack_default_audio_sample_t *) jack_port_get_buffer ( mInputPorts[i], nframes);
++ for(unsigned int i = 0; i < mNumOutputPorts; i++)
++ mJackOutBuf[i] = (jack_default_audio_sample_t *) jack_port_get_buffer ( mOutputPorts[i], nframes);
++
++ return audioCallback(nframes, mJackInBuf, mJackOutBuf);
++}
++
++JackCpp::AudioIO::AudioIO(std::string name, unsigned int inPorts, unsigned int outPorts, bool startServer)
++ throw(std::runtime_error) : mCmdBuffer(256,true)
++{
++ jack_options_t jack_open_options = JackNullOption;
++
++ if(startServer == false)
++ jack_open_options = JackNoStartServer;
++
++ mJackState = notActive;
++
++ //set the error callback
++ jack_set_error_function (error_callback);
++
++ /* try to become a client of the JACK server */
++ if ((mJackClient = jack_client_open (name.c_str(), jack_open_options, NULL)) == 0) {
++ throw std::runtime_error("cannot create client jack server not running?");
++ }
++#ifdef __APPLE__
++ else {
++ // because the mac version of jack is being totally LAME
++ sleep(2);
++ }
++#endif
++
++ //set the shutdown callback
++ jack_on_shutdown (mJackClient, shutdown_callback, this);
++
++ //allocate ports
++ if (inPorts > 0){
++ for(unsigned int i = 0; i < inPorts; i++){
++ std::string portname = "input";
++ portname.append(ToString(i));
++ mInputPorts.push_back(
++ jack_port_register (mJackClient, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0));
++ mPortNames.push_back(portname);
++ }
++ //reserve the data for the jack callback buffers
++ for(unsigned int i = 0; i < mInputPorts.size(); i++)
++ mJackInBuf.push_back(NULL);
++ }
++ if (outPorts > 0){
++ for(unsigned int i = 0; i < outPorts; i++){
++ std::string portname = "output";
++ portname.append(ToString(i));
++ mOutputPorts.push_back(
++ jack_port_register (mJackClient, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0));
++ mPortNames.push_back(portname);
++ }
++ //reserve the data for the jack callback buffers
++ for(unsigned int i = 0; i < mOutputPorts.size(); i++)
++ mJackOutBuf.push_back(NULL);
++ }
++
++ //set up the callback
++ if(0 != jack_set_process_callback (mJackClient, JackCpp::AudioIO::jackProcessCallback, this))
++ throw std::runtime_error("cannot register process callback");
++}
++
++
++JackCpp::AudioIO::~AudioIO(){
++ //make sure to deactiveate the client if we need to
++ switch(mJackState){
++ case active:
++ stop();
++ close();
++ break;
++ case notActive:
++ close();
++ break;
++ default:
++ break;
++ //do nothing
++ }
++}
++
++bool JackCpp::AudioIO::portExists(std::string name){
++ //see if the port name exists
++ std::vector<std::string>::iterator it;
++ it = std::find(mPortNames.begin(),mPortNames.end(), name);
++ if (it != mPortNames.end())
++ return true;
++ else
++ return false;
++}
++
++void JackCpp::AudioIO::reserveOutPorts(unsigned int num)
++ throw(std::runtime_error)
++{
++ if(getState() == active)
++ throw std::runtime_error("reserving ports while the client is running is not supported yet.");
++ mOutputPorts.reserve(num);
++ mJackOutBuf.reserve(num);
++}
++
++void JackCpp::AudioIO::reserveInPorts(unsigned int num)
++ throw(std::runtime_error)
++{
++ if(getState() == active)
++ throw std::runtime_error("reserving ports while the client is running is not supported yet.");
++ mInputPorts.reserve(num);
++ mJackInBuf.reserve(num);
++}
++
++unsigned int JackCpp::AudioIO::inPorts(){
++ return mInputPorts.size();
++}
++
++unsigned int JackCpp::AudioIO::outPorts(){
++ return mOutputPorts.size();
++}
++
++unsigned int JackCpp::AudioIO::addInPort(std::string name)
++ throw(std::runtime_error)
++{
++ if (mJackState == active && mInputPorts.size() == mInputPorts.capacity())
++ throw std::runtime_error("trying to add input ports while the client is running and there are not reserved ports");
++
++ if(portExists(name)){
++ std::string ret_string("cannot register new inport: ");
++ ret_string.append(name);
++ ret_string.append(" port already exists with that name");
++ throw std::runtime_error(ret_string);
++ }
++
++ //allocate the item in the vector
++ jack_port_t * newPort = jack_port_register (mJackClient, name.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
++ if(newPort == NULL){
++ std::string ret_string("cannot register new inport: ");
++ ret_string.append(name);
++ throw std::runtime_error(ret_string);
++ }
++ mInputPorts.push_back(newPort);
++ mPortNames.push_back(name);
++
++ //if we're active then send a command indicating this change
++ if (mJackState == active) {
++ //loop while there isn't space to write
++ while(mCmdBuffer.getWriteSpace() == 0);
++ mCmdBuffer.write(add_in_port);
++ } else
++ mJackInBuf.push_back(NULL);
++
++ return mInputPorts.size() - 1;
++}
++
++//add an output port, if we are active then deactivate and reactivate after
++//maybe we can do this more intelligently in the future?
++unsigned int JackCpp::AudioIO::addOutPort(std::string name)
++ throw(std::runtime_error)
++{
++ if (mJackState == active && mOutputPorts.size() == mOutputPorts.capacity())
++ throw std::runtime_error("trying to add output ports while the client is running and there are not reserved ports");
++
++ if(portExists(name)){
++ std::string ret_string("cannot register new outport: ");
++ ret_string.append(name);
++ ret_string.append(" port already exists with that name");
++ throw std::runtime_error(ret_string);
++ }
++
++ //allocate the item in the vector
++ jack_port_t * newPort = jack_port_register (mJackClient, name.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
++ if(newPort == NULL){
++ std::string ret_string("cannot register new outport: ");
++ ret_string.append(name);
++ throw std::runtime_error(ret_string);
++ }
++ mOutputPorts.push_back(newPort);
++ mPortNames.push_back(name);
++
++ //if we're active then send a command indicating this change
++ if (mJackState == active) {
++ //loop while there isn't space to write
++ while(mCmdBuffer.getWriteSpace() == 0);
++ mCmdBuffer.write(add_out_port);
++ } else
++ mJackOutBuf.push_back(NULL);
++
++ return mOutputPorts.size() - 1;
++}
++
++void JackCpp::AudioIO::connectTo(unsigned int index, std::string destPortName)
++ throw(std::range_error, std::runtime_error)
++{
++ int connect_ret;
++ if (mJackState != active)
++ throw std::runtime_error("client must be active before connecting ports");
++ if(index < mOutputPorts.size()){
++ connect_ret = jack_connect(mJackClient, jack_port_name(mOutputPorts[index]), destPortName.c_str());
++ if(connect_ret != 0 && connect_ret != EEXIST){
++ std::string ret_string("cannot connect source: ");
++ ret_string.append(jack_port_name(mOutputPorts[index]));
++ ret_string.append(" to dest: ");
++ ret_string.append(destPortName);
++ ret_string.append(" does dest exist?");
++ throw std::range_error(ret_string);
++ }
++ } else
++ throw std::range_error("outport index out of range");
++}
++
++void JackCpp::AudioIO::connectFrom(unsigned int index, std::string sourcePortName)
++ throw(std::range_error, std::runtime_error)
++{
++ int connect_ret;
++ if (mJackState != active)
++ throw std::runtime_error("client must be active before connecting ports");
++ if(index < mInputPorts.size()){
++ connect_ret = jack_connect(mJackClient, sourcePortName.c_str(), jack_port_name(mInputPorts[index]));
++ if(connect_ret != 0 && connect_ret != EEXIST){
++ std::string ret_string("cannot connect source: ");
++ ret_string.append(sourcePortName);
++ ret_string.append(" to dest: ");
++ ret_string.append(jack_port_name(mInputPorts[index]));
++ ret_string.append(" does source exist?");
++ throw std::range_error(ret_string);
++ }
++ } else
++ throw std::range_error("inport index out of range");
++}
++
++//XXX should the "free" free the names that these ports point too as well?
++void JackCpp::AudioIO::connectToPhysical(unsigned int index, unsigned physical_index)
++ throw(std::range_error, std::runtime_error)
++{
++ const char **ports;
++ if (mJackState != active)
++ throw std::runtime_error("client must be active before connecting ports");
++ if (index > mOutputPorts.size())
++ throw std::range_error("outport index out of range");
++ ports = jack_get_ports (mJackClient, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
++ if(ports == NULL){
++ throw std::range_error("no physical inports to connect to");
++ }
++ //make sure the port exists
++ for(unsigned int i = 0; i <= physical_index; i++){
++ if(ports[i] == NULL){
++ free(ports);
++ throw std::range_error("physical inport index out of range");
++ }
++ }
++ connectTo(index, ports[physical_index]);
++ free(ports);
++}
++
++//XXX should the "free" free the names that these ports point too as well?
++void JackCpp::AudioIO::connectFromPhysical(unsigned int index, unsigned physical_index)
++ throw(std::range_error, std::runtime_error)
++{
++ const char **ports;
++ if (mJackState != active)
++ throw std::runtime_error("client must be active before connecting ports");
++ if (index > mInputPorts.size())
++ throw std::range_error("inport index out of range");
++ ports = jack_get_ports (mJackClient, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
++ if(ports == NULL){
++ throw std::range_error("no physical outports to connect to");
++ }
++ //make sure the port exists
++ for(unsigned int i = 0; i <= physical_index; i++){
++ if(ports[i] == NULL){
++ free(ports);
++ throw std::range_error("physical outport index out of range");
++ }
++ }
++ connectFrom(index, ports[physical_index]);
++ free(ports);
++}
++
++void JackCpp::AudioIO::disconnectInPort(unsigned int index)
++ throw(std::range_error, std::runtime_error)
++{
++ if (mJackState != active)
++ throw std::runtime_error("client must be active before disconnecting ports");
++ if(index < mInputPorts.size()){
++ jack_port_disconnect(mJackClient, mInputPorts[index]);
++ } else
++ throw std::range_error("inport index out of range");
++}
++
++void JackCpp::AudioIO::disconnectOutPort(unsigned int index)
++ throw(std::range_error, std::runtime_error)
++{
++ if (mJackState != active)
++ throw std::runtime_error("client must be active before disconnecting ports");
++ if(index < mOutputPorts.size()){
++ jack_port_disconnect(mJackClient, mOutputPorts[index]);
++ } else
++ throw std::range_error("outport index out of range");
++}
++
++unsigned int JackCpp::AudioIO::numConnectionsInPort(unsigned int index)
++ throw(std::range_error)
++{
++ if(index < mInputPorts.size())
++ return jack_port_connected(mInputPorts[index]);
++ else
++ throw std::range_error("inport index out of range");
++}
++
++unsigned int JackCpp::AudioIO::numConnectionsOutPort(unsigned int index)
++ throw(std::range_error)
++{
++ if(index < mOutputPorts.size())
++ return jack_port_connected(mOutputPorts[index]);
++ else
++ throw std::range_error("outport index out of range");
++}
++
++unsigned int JackCpp::AudioIO::numPhysicalDestinationPorts(){
++ const char **ports;
++ unsigned int cnt = 0;
++ ports = jack_get_ports (mJackClient, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
++ if (ports != NULL){
++ while(ports[cnt] != NULL)
++ cnt++;
++ free(ports);
++ return cnt;
++ } else
++ return 0;
++}
++
++unsigned int JackCpp::AudioIO::numPhysicalSourcePorts(){
++ const char **ports;
++ unsigned int cnt = 0;
++ //XXX is this really correct? we should get the naming right...
++ ports = jack_get_ports (mJackClient, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
++ if (ports != NULL){
++ while(ports[cnt] != NULL)
++ cnt++;
++ free(ports);
++ return cnt;
++ } else
++ return 0;
++}
++
++std::string JackCpp::AudioIO::getInputPortName(unsigned int index)
++ throw(std::range_error)
++{
++ if(index < mInputPorts.size())
++ return std::string(jack_port_name(mInputPorts[index]));
++ else
++ throw std::range_error("inport index out of range");
++
++}
++std::string JackCpp::AudioIO::getOutputPortName(unsigned int index)
++ throw(std::range_error)
++{
++ if(index < mOutputPorts.size())
++ return std::string(jack_port_name(mOutputPorts[index]));
++ else
++ throw std::range_error("outport index out of range");
++}
++
++void JackCpp::AudioIO::start()
++ throw(std::runtime_error)
++{
++ //update these so that the callback can use them
++ if(mJackState != active){
++ mNumOutputPorts = mOutputPorts.size();
++ mNumInputPorts = mInputPorts.size();
++ }
++ if (jack_activate(mJackClient) != 0)
++ throw std::runtime_error("cannot activate the client");
++ mJackState = active;
++}
++
++void JackCpp::AudioIO::stop()
++ throw(std::runtime_error)
++{
++ if (jack_deactivate(mJackClient) != 0)
++ throw std::runtime_error("cannot deactivate the client");
++ mJackState = notActive;
++}
++
++void JackCpp::AudioIO::close()
++ throw(std::runtime_error)
++{
++ if (jack_client_close(mJackClient) != 0)
++ throw std::runtime_error("cannot close the client");
++ mJackState = closed;
++}
++
++float JackCpp::AudioIO::getCpuLoad(){
++ return jack_cpu_load(mJackClient);
++}
++
++jack_nframes_t JackCpp::AudioIO::getSampleRate(){
++ return jack_get_sample_rate(mJackClient);
++}
++
++jack_nframes_t JackCpp::AudioIO::getBufferSize(){
++ return jack_get_buffer_size(mJackClient);
++}
++
+Index: xbmc/cores/AudioRenderers/jackaudioio.hpp
+===================================================================
+--- xbmc/cores/AudioRenderers/jackaudioio.hpp (revision 0)
++++ xbmc/cores/AudioRenderers/jackaudioio.hpp (revision 1806)
+@@ -0,0 +1,299 @@
++//C++ Classes that wrap JACK
++//Copyright 2007 Alex Norman
++//
++//This file is part of JACKC++.
++//
++//JACKC++ is free software: you can redistribute it and/or modify
++//it under the terms of the GNU General Public License as published by
++//the Free Software Foundation, either version 3 of the License, or
++//(at your option) any later version.
++//
++//JACKC++ is distributed in the hope that it will be useful,
++//but WITHOUT ANY WARRANTY; without even the implied warranty of
++//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++//GNU General Public License for more details.
++//
++//You should have received a copy of the GNU General Public License
++//along with JACKC++. If not, see <http://www.gnu.org/licenses/>.
++
++#ifndef JACK_AUDIO_IO_H
++#define JACK_AUDIO_IO_H
++
++extern "C" {
++#include <jack/jack.h>
++#include <jack/types.h>
++#include <jack/ringbuffer.h>
++}
++#include <string>
++#include <vector>
++#include <stdexcept>
++#include "jackringbuffer.hpp"
++
++namespace JackCpp {
++
++/**
++@class AudioIO
++
++@brief This is an abstract class that provides a jack callback method.
++
++This abstract class wraps the Jack Audio IO functionality needed for basic
++audio input and output. In order to create your own jack client you simply
++make your own class that inherits from this class and overloads audioCallback.
++In that method you can get audio in from jack and write it out to jack.
++
++@author Alex Norman
++
++*/
++
++ class AudioIO {
++ public:
++ ///An enum indicating the state of our jack client
++ enum jack_state_t {notActive,active,closed};
++ ///A typedef so so that we don't always have to write std::vector<jack_default_audio_sample_t *>
++ typedef std::vector<jack_default_audio_sample_t *> audioBufVector;
++ private:
++ //commands
++ enum cmd_t {add_in_port, add_out_port};
++ RingBuffer<cmd_t> mCmdBuffer;
++ /* the client */
++ jack_client_t *mJackClient;
++ // an vector of i/o ports
++ std::vector<jack_port_t *> mOutputPorts;
++ std::vector<jack_port_t *> mInputPorts;
++
++ //these are only accessed by the callback [once it is activated]
++ //they will usually be equal mOutputPorts.size() etc, except when
++ //a new port is added, before the callback
++ unsigned int mNumOutputPorts;
++ unsigned int mNumInputPorts;
++
++ //these items are used for grabbing data for the jack callback
++ audioBufVector mJackInBuf;
++ audioBufVector mJackOutBuf;
++ //this stores the state of this jack process [active,notActive,closed]
++ jack_state_t mJackState;
++ //this prepares the input/output buffers to be passed
++ //to the callback function that a user writes
++ //XXX should this be virtual?
++ inline int jackToClassAudioCallback(jack_nframes_t nframes);
++ std::vector<std::string> mPortNames;
++ protected:
++ /**
++ @brief The method that the user must overload in order to actually process jack data.
++ \param nframes the number frames to process
++ \param inBufs a vector of audio buffers
++ \param outBufs a vector of audio buffers
++ \return 0 on success, non zero on error, which will cause jack to remove the client from the process graph
++ */
++ virtual int audioCallback(jack_nframes_t nframes,
++ audioBufVector inBufs,
++ audioBufVector outBufs) = 0;
++
++ public:
++ /**
++ @brief The Constructor
++ \param name string indicating the name of the jack client to create
++ \param inPorts an unsigned integer indicating the number of default input ports to create
++ \param outPorts an unsigned integer indicating the number of default output ports to create
++ \param startServer a boolean indicating whether to start a jack server if one isn't already running
++ \sa audioCallback
++ */
++ AudioIO(std::string name,
++ unsigned int inPorts = 0,
++ unsigned int outPorts = 2,
++#ifdef __APPLE__
++ bool startServer = false)
++#else
++ bool startServer = true)
++#endif
++ throw(std::runtime_error);
++
++ ///The Destructor
++ virtual ~AudioIO();
++
++ /**
++ @brief The callback that jack actually gets [static].
++
++ This is a static method that the C jack callback calls, users
++ should not need to override this method.
++
++ \param nframes the number frames to process
++ \param arg a pointer to our AudioIO object
++ \return the actual number of frames processed
++ \sa audioCallback
++ */
++ static int jackProcessCallback(jack_nframes_t nframes, void *arg);
++
++ ///See if a port with the name "name" exists for our client
++ bool portExists(std::string name);
++
++ /**
++ @brief Reserve output ports
++
++ This method must be called before the client is started. This
++ reserves a number of ports so that they can be safely created while
++ the client is running. The number indicates the maximum number of ports
++ that can be created while the client is running. This number includes
++ those ports that a have already been created, so if you've already created
++ x ports and you reserve y ports total, you can only create y - x ports while
++ the client is running.
++ \param num an integer indicating the number of output ports to reserve
++ */
++ virtual void reserveOutPorts(unsigned int num)
++ throw(std::runtime_error);
++ /**
++ @brief Reserve input ports
++
++ This method must be called before the client is started. This
++ reserves a number of ports so that they can be safely created while
++ the client is running. The number indicates the maximum number of ports
++ that can be created while the client is running. This number includes
++ those ports that a have already been created, so if you've already created
++ x ports and you reserve y ports total, you can only create y - x ports while
++ the client is running.
++ \param num an integer indicating the number of input ports to reserve
++ */
++ virtual void reserveInPorts(unsigned int num)
++ throw(std::runtime_error);
++
++ ///Start the jack client.
++ void start()
++ throw(std::runtime_error);
++ ///Stop the jack client.
++ void stop()
++ throw(std::runtime_error);
++ ///Close the jack client.
++ void close()
++ throw(std::runtime_error);
++
++ ///Get the number of jack input ports
++ unsigned int inPorts();
++ ///Get the number of jack output ports
++ unsigned int outPorts();
++
++ /**
++ @brief Add a jack input port to our client
++ \param name string the name of the port to add
++ \return the number of total input ports
++ */
++ virtual unsigned int addInPort(std::string name)
++ throw(std::runtime_error);
++ /**
++ @brief Add a jack output port to our client
++ \param name string the name of the port to add
++ \return the number of total output ports
++ */
++ virtual unsigned int addOutPort(std::string name)
++ throw(std::runtime_error);
++
++ /**
++ @brief Connect our output to a jack client's source port.
++ \param index the index of our output port to connect from.
++ \param sourcePortName the client:port name to connect to
++ */
++ void connectTo(unsigned int index, std::string sourcePortName)
++ throw(std::range_error, std::runtime_error);
++ /**
++ @brief Connect our input to a jack client's destination port.
++ \param index the index of our input port to connect to
++ \param destPortName the client:port name to connect from
++ */
++ void connectFrom(unsigned int index, std::string destPortName)
++ throw(std::range_error, std::runtime_error);
++ /**
++ @brief Connect our output port to a physical output port
++ \param index the index of our output port to connect from
++ \param physical_index the physical output port index to connect to
++ */
++ void connectToPhysical(unsigned int index, unsigned physical_index)
++ throw(std::range_error, std::runtime_error);
++ /**
++ @brief Connect our input port to a physical input port
++ \param index the index of our input port to connect to
++ \param physical_index the physical input port index to connect from
++ */
++ void connectFromPhysical(unsigned int index, unsigned physical_index)
++ throw(std::range_error, std::runtime_error);
++ ///Disconnect input port from all connections
++ void disconnectInPort(unsigned int index)
++ throw(std::range_error, std::runtime_error);
++ ///Disconnect output port from all connections
++ void disconnectOutPort(unsigned int index)
++ throw(std::range_error, std::runtime_error);
++
++ ///Get the number of connections to our input port
++ unsigned int numConnectionsInPort(unsigned int index)
++ throw(std::range_error);
++ ///Get the number of connections to our output port
++ unsigned int numConnectionsOutPort(unsigned int index)
++ throw(std::range_error);
++
++ /**
++ @brief Get the number of physical audio input ports
++ These are ports that can send audio to your client
++ */
++ unsigned int numPhysicalSourcePorts();
++ /**
++ @brief Get the number of physical audio output ports
++ These are ports that your client can send audio to
++ */
++ unsigned int numPhysicalDestinationPorts();
++
++ ///Get the name of our client's input port
++ std::string getInputPortName(unsigned int index)
++ throw(std::range_error);
++ ///Get the name of our client's output port
++ std::string getOutputPortName(unsigned int index)
++ throw(std::range_error);
++
++ /**
++ @brief This method is called when Jack shuts down.
++ Override if you want to do something when jack shuts down.
++ */
++ virtual void jackShutdownCallback();
++ /**
++ @brief The current CPU load estimated by JACK
++
++ This is a running average of the time it takes to execute a full
++ process cycle for all clients as a percentage of the real time
++ available per cycle determined by the buffer size and sample rate.
++ */
++ float getCpuLoad();
++ ///Get the sample rate
++ jack_nframes_t getSampleRate();
++ ///Get the jack buffer size
++ jack_nframes_t getBufferSize();
++ ///Check to see if the client is running in real time mode
++ bool isRealTime(){return jack_is_realtime(mJackClient);}
++ /**
++ @brief Get the name of our client
++
++ This might not be exactly the same as the name we provided to the
++ constructor
++
++ \return a string indicating the name of our client.
++ */
++ std::string getName(){return std::string(jack_get_client_name(mJackClient));}
++ ///Get the state of our Jack client.
++ jack_state_t getState(){return mJackState;}
++
++ /**
++ @brief Get an estimate of the current time in frames
++
++ This is a running counter, no significance should be attached to
++ its value, but it can be compared to a previously returned value.
++ \return an estimate of the current time in frames.
++ */
++ jack_nframes_t getFrameTime(){return jack_frame_time(mJackClient);}
++
++ /**
++ @brief Get the time in frames since the JACK server began the current process cycle
++
++ \return the time in frames that has passed since the JACK server began the current process cycle
++ */
++ jack_nframes_t getFramesSinceCycleStart(){return jack_frames_since_cycle_start(mJackClient);}
++ };
++
++}
++
++#endif
+Index: xbmc/cores/AudioRenderers/jackringbuffer.hpp
+===================================================================
+--- xbmc/cores/AudioRenderers/jackringbuffer.hpp (revision 0)
++++ xbmc/cores/AudioRenderers/jackringbuffer.hpp (revision 1806)
+@@ -0,0 +1,205 @@
++//C++ Classes that wrap JACK
++//Copyright 2007 Alex Norman
++//
++//This file is part of JACKC++.
++//
++//JACKC++ is free software: you can redistribute it and/or modify
++//it under the terms of the GNU General Public License as published by
++//the Free Software Foundation, either version 3 of the License, or
++//(at your option) any later version.
++//
++//JACKC++ is distributed in the hope that it will be useful,
++//but WITHOUT ANY WARRANTY; without even the implied warranty of
++//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++//GNU General Public License for more details.
++//
++//You should have received a copy of the GNU General Public License
++//along with JACKC++. If not, see <http://www.gnu.org/licenses/>.
++
++#ifndef JACK_RING_BUFFER_CLASS_H
++#define JACK_RING_BUFFER_CLASS_H
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++extern "C" {
++#include <jack/ringbuffer.h>
++}
++#include <string.h>
++
++namespace JackCpp {
++
++template<typename Type>
++
++/**
++@class RingBuffer
++
++@brief This template class wraps the Jack lock-free ringbuffer.
++
++This class creates a lock-free ring buffer that accepts a specific data type.
++
++The key attribute of a ringbuffer is that it can be safely accessed by two
++threads simultaneously -- one reading from the buffer and the other writing to
++it -- without using any synchronization or mutual exclusion primitives. For
++this to work correctly, there can only be a single reader and a single writer
++thread. Their identities cannot be interchanged.
++
++@author Alex Norman
++
++*/
++ class RingBuffer {
++ private:
++ jack_ringbuffer_t *mRingBufferPtr;
++ size_t mLength;
++ public:
++ /**
++ @brief The Constructor
++ \param size the number of items that the ring buffer should be able to hold
++ \param mlock a boolean indicating whether or not the ring buffer should be locked in memory
++ */
++ RingBuffer(size_t size, bool mlock = false){
++ mLength = size;
++ mRingBufferPtr = jack_ringbuffer_create(mLength * sizeof(Type));
++
++ //should we lock the memory for the ring buffer?
++ if(mlock)
++ jack_ringbuffer_mlock(mRingBufferPtr);
++ }
++ ///The Destructor
++ ~RingBuffer(){
++ if(mRingBufferPtr != NULL)
++ jack_ringbuffer_free(mRingBufferPtr);
++ }
++
++ ///Get the total length of the ring buffer
++ size_t length(){
++ return mLength;
++ }
++
++ ///Get the number of items that can be read at this time
++ size_t getReadSpace(){
++ return jack_ringbuffer_read_space(mRingBufferPtr) / sizeof(Type);
++ }
++
++ ///Get the number of items that can be written at this time
++ size_t getWriteSpace(){
++ return jack_ringbuffer_write_space(mRingBufferPtr) / sizeof(Type);
++ }
++
++ /**
++ @brief Read into dest
++
++ Read from the buffer into a variable.
++
++ \param dest an item to be read into
++ */
++ void read(Type &dest){
++ if(getReadSpace() <= 0){
++ //throw error!!!!
++ return;
++ }
++ jack_ringbuffer_read(mRingBufferPtr, (char *)&dest, sizeof(Type));
++ }
++
++ /**
++ @brief Read into an array
++
++ Read from the buffer into an array.
++
++ \param dest an array to be read into
++ \param cnt the number of elements to read into this array
++ */
++ void read(Type *dest, unsigned cnt){
++ jack_ringbuffer_data_t readVec[2];
++ unsigned int read_size = sizeof(Type) * cnt;
++ if(getReadSpace() <= 0){
++ //throw error!!!!
++ return;
++ }
++
++ //get the readvector
++ jack_ringbuffer_get_read_vector(mRingBufferPtr, readVec);
++
++ //if the first vector has enough data then just read from there
++ if(readVec[0].len >= read_size){
++ memcpy(dest, readVec[0].buf, read_size);
++ } else {
++ //if the first vector is zero length then read from the second
++ if(readVec[0].len == 0){
++ memcpy(dest, readVec[1].buf, read_size);
++ } else {
++ //this gets tricky
++ char * byterep = (char *)dest;
++ //first read the data out of the first vector
++ memcpy(byterep, readVec[0].buf, readVec[0].len);
++ //then read the rest out of the second
++ memcpy(byterep + readVec[0].len, readVec[1].buf, read_size - readVec[0].len);
++ }
++ }
++ //advance the read pointer
++ jack_ringbuffer_read_advance(mRingBufferPtr, read_size);
++ }
++
++ /**
++ @brief Write into the ring buffer.
++
++ \param src the value to write
++ */
++ void write(Type src){
++ if(getWriteSpace() <= 0){
++ //throw error!!!!
++ return;
++ }
++ jack_ringbuffer_write(mRingBufferPtr, (char *)&src, sizeof(Type));
++ }
++
++ /**
++ @brief Write an array of values into the ring buffer.
++
++ \param src an array of values to write
++ \param cnt the number of items from the array to write into our buffer
++ */
++ void write(Type *src, unsigned int cnt){
++ jack_ringbuffer_data_t writeVec[2];
++ unsigned int write_size = sizeof(Type) * cnt;
++ if(cnt > getWriteSpace()){
++ //throw error!!!!
++ return;
++ }
++
++ //get the write vector
++ jack_ringbuffer_get_write_vector(mRingBufferPtr, writeVec);
++ //if there is enough room in the first vector then just write there
++ if(writeVec[0].len >= write_size){
++ memcpy(writeVec[0].buf,src,write_size);
++ } else {
++ //if there is no room in the first vector then write into the second
++ if(writeVec[0].len == 0){
++ memcpy(writeVec[1].buf,src,write_size);
++ } else {
++ //this is more tricky, we have to split the data up
++ char * byterep = (char *)src;
++ //copy the first chunck
++ memcpy(writeVec[0].buf, byterep, writeVec[0].len);
++ //copy the second chunck
++ memcpy(writeVec[1].buf, byterep + writeVec[0].len, write_size - writeVec[0].len);
++ }
++ }
++ jack_ringbuffer_write_advance(mRingBufferPtr, write_size);
++ }
++
++ /**
++ @brief Reset
++
++ This is not threadsafe. This resets the read and write pointers,
++ effectively making the ring buffer empty.
++ */
++ void reset(){
++ jack_ringbuffer_reset(mRingBufferPtr);
++ }
++ };
++
++}
++
++#endif
+Index: xbmc/cores/AudioRenderers/jackblockingaudioio.cpp
+===================================================================
+--- xbmc/cores/AudioRenderers/jackblockingaudioio.cpp (revision 0)
++++ xbmc/cores/AudioRenderers/jackblockingaudioio.cpp (revision 1806)
+@@ -0,0 +1,181 @@
++//C++ Classes that wrap JACK
++//Copyright 2007 Alex Norman
++//
++//This file is part of JACKC++.
++//
++//JACKC++ is free software: you can redistribute it and/or modify
++//it under the terms of the GNU General Public License as published by
++//the Free Software Foundation, either version 3 of the License, or
++//(at your option) any later version.
++//
++//JACKC++ is distributed in the hope that it will be useful,
++//but WITHOUT ANY WARRANTY; without even the implied warranty of
++//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++//GNU General Public License for more details.
++//
++//You should have received a copy of the GNU General Public License
++//along with JACKC++. If not, see <http://www.gnu.org/licenses/>.
++
++#include "jackblockingaudioio.hpp"
++#include <unistd.h>
++#define MIN(x,y) ((x) < (y) ? (x) : (y))
++
++#if 0
++#include <iostream>
++using std::cerr;
++using std::cout;
++using std::endl;
++#endif
++
++//allocate input and output buffers
++JackCpp::BlockingAudioIO::BlockingAudioIO(std::string name,
++ unsigned int inChans, unsigned int outChans,
++ unsigned int inBufSize, unsigned int outBufSize,
++ bool startServer) throw(std::runtime_error):
++ AudioIO(name, inChans, outChans, startServer),
++ mOutputBufferMaxSize((unsigned int)getSampleRate()),
++ mInputBufferMaxSize((unsigned int)getSampleRate())
++{
++ if(inBufSize < 2 * getBufferSize())
++ inBufSize = 2 * getBufferSize();
++ else if (inBufSize > mInputBufferMaxSize)
++ inBufSize = mInputBufferMaxSize;
++ if(outBufSize < 2 * getBufferSize())
++ outBufSize = 2 * getBufferSize();
++ else if (outBufSize > mOutputBufferMaxSize)
++ outBufSize = mOutputBufferMaxSize;
++
++ //set the amount of the ring buffer that we leave free
++ mOutputBufferFreeSize = mOutputBufferMaxSize - outBufSize;
++ mInputBufferFreeSize = mInputBufferMaxSize - inBufSize;
++
++ //create input and output buffers, give them extra space to work with and memory lock them
++ for(unsigned int i = 0; i < outChans; i++)
++ mUserOutBuff.push_back(new RingBuffer<jack_default_audio_sample_t>(mOutputBufferMaxSize, true));
++ for(unsigned int i = 0; i < inChans; i++)
++ mUserInBuff.push_back(new RingBuffer<jack_default_audio_sample_t>(mInputBufferMaxSize, true));
++}
++
++//clean up the buffers we allocated
++JackCpp::BlockingAudioIO::~BlockingAudioIO(){
++ stop();
++ for(std::vector<RingBuffer<jack_default_audio_sample_t> *>::iterator it = mUserOutBuff.begin();
++ it != mUserOutBuff.end(); it++)
++ delete *it;
++ for(std::vector<RingBuffer<jack_default_audio_sample_t> *>::iterator it = mUserInBuff.begin();
++ it != mUserInBuff.end(); it++)
++ delete *it;
++}
++
++//wait until we can write, then write
++void JackCpp::BlockingAudioIO::write(unsigned int channel, jack_default_audio_sample_t val){
++ if (channel >= outPorts())
++ return;
++ while(mUserOutBuff[channel]->getWriteSpace() <= mOutputBufferFreeSize)
++ usleep(10);
++ mUserOutBuff[channel]->write(val);
++}
++
++//we we can write then write, otherwise return false
++bool JackCpp::BlockingAudioIO::tryWrite(unsigned int channel, jack_default_audio_sample_t val){
++ if (channel < outPorts() && mUserOutBuff[channel]->getWriteSpace() > mOutputBufferFreeSize){
++ mUserOutBuff[channel]->write(val);
++ return true;
++ }
++ return false;
++}
++
++//wait until we can read, then return the value
++jack_default_audio_sample_t JackCpp::BlockingAudioIO::read(unsigned int channel){
++ jack_default_audio_sample_t val;
++ if (channel >= inPorts())
++ return 0;
++ while(mUserInBuff[channel]->getReadSpace() == 0)
++ usleep(10);
++ mUserInBuff[channel]->read(val);
++ return val;
++}
++
++//if we cannot read then return false, otherwise, read and return true
++bool JackCpp::BlockingAudioIO::tryRead(unsigned int channel, jack_default_audio_sample_t &val){
++ if (channel >= inPorts() || mUserInBuff[channel]->getReadSpace() == 0)
++ return false;
++ mUserInBuff[channel]->read(val);
++ return true;
++}
++
++void JackCpp::BlockingAudioIO::reserveOutPorts(unsigned int num)
++ throw(std::runtime_error)
++{
++ AudioIO::reserveOutPorts(num);
++ mUserOutBuff.reserve(num);
++}
++
++void JackCpp::BlockingAudioIO::reserveInPorts(unsigned int num)
++ throw(std::runtime_error)
++{
++ AudioIO::reserveInPorts(num);
++ mUserInBuff.reserve(num);
++}
++
++unsigned int JackCpp::BlockingAudioIO::addInPort(std::string name)
++ throw(std::runtime_error)
++{
++ unsigned int ret;
++ if(getState() == AudioIO::active)
++ throw std::runtime_error("JackCpp::BlockingAudioIO::addInPort not allowed while the client is active");
++ ret = AudioIO::addInPort(name);
++ mUserInBuff.push_back(new RingBuffer<jack_default_audio_sample_t>(mInputBufferMaxSize, true));
++ return ret;
++}
++
++unsigned int JackCpp::BlockingAudioIO::addOutPort(std::string name)
++ throw(std::runtime_error)
++{
++ unsigned int ret;
++ if(getState() == AudioIO::active)
++ throw std::runtime_error("JackCpp::BlockingAudioIO::addOutPort not allowed while the client is active");
++ ret = AudioIO::addOutPort(name);
++ mUserOutBuff.push_back(new RingBuffer<jack_default_audio_sample_t>(mOutputBufferMaxSize, true));
++ return ret;
++}
++
++//read the jack input buffers into the user input buffers
++//write the user output buffers into the jack output buffers
++int JackCpp::BlockingAudioIO::audioCallback(jack_nframes_t nframes,
++ audioBufVector inBufs,
++ audioBufVector outBufs){
++
++ //only try to write as much as we have space to write
++ unsigned int numToWrite = MIN(mUserOutBuff[0]->getReadSpace(), nframes);
++ unsigned int numToRead = MIN(mUserInBuff[0]->getWriteSpace(), nframes);
++
++ //make sure we leave the amount of free space we require
++ if(mUserInBuff[0]->getWriteSpace() - numToRead < mInputBufferFreeSize)
++ numToRead = mUserInBuff[0]->getWriteSpace() - mInputBufferFreeSize;
++
++ //if (numToWrite < nframes)
++ //cerr << "oops" << endl;
++
++ //read get inputs
++ for(unsigned int i = 0; i < inPorts(); i++){
++ for(unsigned int j = 0; j < numToRead; j++)
++ mUserInBuff[i]->write(inBufs[i][j]);
++ }
++
++ //write output
++ for(unsigned int i = 0; i < outPorts(); i++){
++ for(unsigned int j = 0; j < numToWrite; j++){
++ jack_default_audio_sample_t val;
++ mUserOutBuff[i]->read(val);
++ outBufs[i][j] = val;
++ }
++ //write zeros for the rest
++ for(unsigned int j = numToWrite; j < nframes; j++)
++ outBufs[i][j] = 0.0;
++ //if(numToWrite < nframes)
++ //cerr << "oops" << endl;
++ }
++ return 0;
++}
++