Index: configure.ac===================================================================--- configure.ac (revision 28031)+++ configure.ac (working copy)@@ -254,6 +254,16 @@ AC_ARG_ENABLE(lua-binaries, AS_HELP_STRING([--enable-lua-binaries],[Build lua and luac]), enable_lua_binaries=$enableval, enable_lua_binaries=no) AM_CONDITIONAL(BUILD_LUA_BINARIES, test "$enable_lua_binaries" = "yes" )+AC_ARG_ENABLE(pulse, AS_HELP_STRING([--enable-pulse],[enable PulseAudio output]), enable_pulse=$enableval, enable_pulse=no)+have_pulse=no+if test "x$enable_pulse" = "xyes"; then+ PKG_CHECK_MODULES(PULSE, [ libpulse-simple >= 0.9 ],+ [have_pulse=yes],[have_pulse=no])+ AC_SUBST(PULSE_LIBS)+ AC_SUBST(PULSE_CFLAGS)+fi+AM_CONDITIONAL(HAVE_PULSE, test "x$have_pulse" = "xyes" )+ AC_CONFIG_FILES(Makefile) AC_CONFIG_FILES(src/Makefile) AC_OUTPUTIndex: src/arch/Sound/RageSoundDriver_Pulse.cpp===================================================================--- src/arch/Sound/RageSoundDriver_Pulse.cpp (revision 0)+++ src/arch/Sound/RageSoundDriver_Pulse.cpp (revision 0)@@ -0,0 +1,166 @@+#include "global.h"+#include "RageSoundDriver_Pulse.h"++#include "RageLog.h"+#include "RageSound.h"+#include "RageSoundManager.h"+#include "RageUtil.h"+#include "PrefsManager.h"++#include <errno.h>+#include <string.h>+#include <pulse/error.h>++REGISTER_SOUND_DRIVER_CLASS( Pulse );++/* samples */+const int channels = 2;+const int bytes_per_frame = channels*2; /* 16-bit */+const int chunk_order = 12;+const int num_chunks = 2; //4;+const int buffersize = num_chunks * (1 << (chunk_order-1)); /* in bytes */+const int buffersize_frames = buffersize/bytes_per_frame; /* in frames */++int RageSoundDriver_Pulse::MixerThread_start(void *p)+{+ ((RageSoundDriver_Pulse *) p)->MixerThread();+ return 0;+}++void RageSoundDriver_Pulse::MixerThread()+{+ /* We want to set a higher priority, but Unix only lets root renice+ * < 0, which is silly. Give it a try, anyway. */+ int status = nice( -10 );+ if( status != -1 )+ LOG->Trace( "Set MixerThread nice value to %d", status );++ while( !shutdown )+ {+ GetData();++ usleep( 10000 );+ }+}++void RageSoundDriver_Pulse::SetupDecodingThread()+{+ int status = nice( -5 );+ if( status != -1 )+ LOG->Trace( "Set DecodingThread nice value to %d", status );+}++bool RageSoundDriver_Pulse::GetData()+{+ const int chunksize = buffersize;++ static int16_t *buf = NULL;+ if(!buf)+ buf = new int16_t[chunksize / sizeof(int16_t)];++ this->Mix( buf, chunksize/bytes_per_frame, last_cursor_pos, GetPosition() );++ if (pa_simple_write( s, buf, chunksize, &err ) < 0)+ return true; // need more data++ /* Increment last_cursor_pos. */+ last_cursor_pos += chunksize / bytes_per_frame;++ return false; // have enough data+}++int64_t RageSoundDriver_Pulse::GetPosition() const+{+ return last_cursor_pos - (buffersize / bytes_per_frame);+ //return last_cursor_pos;+}++RageSoundDriver_Pulse::RageSoundDriver_Pulse()+{+ s = NULL;+ shutdown = false;+ last_cursor_pos = 0;+}++RString RageSoundDriver_Pulse::Init()+{+ samplerate = PREFSMAN->m_iSoundPreferredSampleRate;+ if( samplerate == 0 )+ samplerate = 44100;++ spec.format = PA_SAMPLE_S16LE;+ spec.channels = channels;+ spec.rate = samplerate;++ //bufattr.maxlength = 4096;+ bufattr.maxlength = buffersize * 2;++ s = pa_simple_new(+ NULL, // default server+ "StepMania", // app name+ PA_STREAM_PLAYBACK, // playback+ NULL, // default device+ "Audio", // stream description+ &spec, // sample spec+ NULL, // default channel map+ &bufattr, // h4xed buffering+ &err // error code+ );+ if (s == NULL)+ return ssprintf( "RageSoundDriver_Pulse: Couldn't connect to Pulse server: %s", pa_strerror(err) );++ StartDecodeThread();++ MixingThread.SetName( "RageSoundDriver_Pulse" );+ MixingThread.Create( MixerThread_start, this );++ return "";+}++RageSoundDriver_Pulse::~RageSoundDriver_Pulse()+{+ if( MixingThread.IsCreated() )+ {+ /* Signal the mixing thread to quit. */+ shutdown = true;+ LOG->Trace("Shutting down mixer thread ...");+ MixingThread.Wait();+ LOG->Trace("Mixer thread shut down.");+ }++ if (s != NULL)+ pa_simple_free(s);+}++float RageSoundDriver_Pulse::GetPlayLatency() const+{+ //return (1.0f / samplerate) * (buffersize_frames - chunksize_frames);+ return pa_simple_get_latency(s, NULL) / 1000000.0f;+ //return 0;+}++/*+ * (c) 2002-2004 Glenn Maynard+ * (c) 2009 Ondrej Hosek+ * All rights reserved.+ * + * Permission is hereby granted, free of charge, to any person obtaining a+ * copy of this software and associated documentation files (the+ * "Software"), to deal in the Software without restriction, including+ * without limitation the rights to use, copy, modify, merge, publish,+ * distribute, and/or sell copies of the Software, and to permit persons to+ * whom the Software is furnished to do so, provided that the above+ * copyright notice(s) and this permission notice appear in all copies of+ * the Software and that both the above copyright notice(s) and this+ * permission notice appear in supporting documentation.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF+ * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS+ * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT+ * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR+ * PERFORMANCE OF THIS SOFTWARE.+ */Index: src/arch/Sound/RageSoundDriver_Pulse.h===================================================================--- src/arch/Sound/RageSoundDriver_Pulse.h (revision 0)+++ src/arch/Sound/RageSoundDriver_Pulse.h (revision 0)@@ -0,0 +1,65 @@+#ifndef RAGE_SOUND_PULSE+#define RAGE_SOUND_PULSE++#include "RageSoundDriver.h"+#include "RageThreads.h"+#include "RageTimer.h"++#include <pulse/simple.h>++class RageSoundDriver_Pulse: public RageSoundDriver+{+ pa_simple *s;+ pa_sample_spec spec;+ pa_buffer_attr bufattr;++ bool shutdown;+ int last_cursor_pos;+ int samplerate;++ static int MixerThread_start(void *p);+ void MixerThread();+ RageThread MixingThread;++ int err;++public:+ bool GetData();+ int GetSampleRate() const { return samplerate; }++ /* virtuals: */+ int64_t GetPosition() const;+ float GetPlayLatency() const;+ void SetupDecodingThread();++ RageSoundDriver_Pulse();+ RString Init();+ ~RageSoundDriver_Pulse();+};++#endif++/*+ * (c) 2002-2004 Glenn Maynard+ * (c) 2009 Ondrej Hosek+ * All rights reserved.+ * + * Permission is hereby granted, free of charge, to any person obtaining a+ * copy of this software and associated documentation files (the+ * "Software"), to deal in the Software without restriction, including+ * without limitation the rights to use, copy, modify, merge, publish,+ * distribute, and/or sell copies of the Software, and to permit persons to+ * whom the Software is furnished to do so, provided that the above+ * copyright notice(s) and this permission notice appear in all copies of+ * the Software and that both the above copyright notice(s) and this+ * permission notice appear in supporting documentation.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF+ * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS+ * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT+ * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR+ * PERFORMANCE OF THIS SOFTWARE.+ */Index: src/arch/arch_default.h===================================================================--- src/arch/arch_default.h (revision 28031)+++ src/arch/arch_default.h (working copy)@@ -49,7 +49,7 @@ #define DEFAULT_INPUT_DRIVER_LIST "X11" #endif #define DEFAULT_MOVIE_DRIVER_LIST "Theora,FFMpeg,Null"-#define DEFAULT_SOUND_DRIVER_LIST "ALSA-sw,OSS,Null"+#define DEFAULT_SOUND_DRIVER_LIST "Pulse,ALSA-sw,OSS,Null" #else #error Which arch? #endifIndex: src/Makefile.am===================================================================--- src/Makefile.am (revision 28031)+++ src/Makefile.am (working copy)@@ -198,6 +198,12 @@ Sound += arch/Sound/RageSoundDriver_OSS.cpp arch/Sound/RageSoundDriver_OSS.h endif+if HAVE_PULSE+Sound += arch/Sound/RageSoundDriver_Pulse.cpp arch/Sound/RageSoundDriver_Pulse.h+AM_CXXFLAGS += $(PULSE_CFLAGS)+AM_LDFLAGS += $(PULSE_LIBS)+endif+ if HAVE_ALSA Sound += arch/Sound/ALSA9Dynamic.cpp arch/Sound/ALSA9Dynamic.h arch/Sound/ALSA9Functions.h \ arch/Sound/ALSA9Helpers.cpp arch/Sound/ALSA9Helpers.h \