Fix indentation to match everything else.

This commit is contained in:
Colby Klein
2009-11-09 09:00:26 +00:00
parent dc5e2c1a8b
commit 22e207caf1
2 changed files with 268 additions and 272 deletions
@@ -15,14 +15,14 @@ REGISTER_SOUND_DRIVER_CLASS2( Pulse, PulseAudio );
/* Constructor */
RageSoundDriver_PulseAudio::RageSoundDriver_PulseAudio()
: RageSoundDriver(),
m_LastPosition(0), m_SampleRate(0), m_Error(NULL),
m_Sem("Pulseaudio Synchronization Semaphore"),
m_PulseMainLoop(NULL), m_PulseCtx(NULL), m_PulseStream(NULL)
: RageSoundDriver(),
m_LastPosition(0), m_SampleRate(0), m_Error(NULL),
m_Sem("Pulseaudio Synchronization Semaphore"),
m_PulseMainLoop(NULL), m_PulseCtx(NULL), m_PulseStream(NULL)
{
m_SampleRate = PREFSMAN->m_iSoundPreferredSampleRate;
if( m_SampleRate == 0 )
m_SampleRate = 44100;
m_SampleRate = PREFSMAN->m_iSoundPreferredSampleRate;
if( m_SampleRate == 0 )
m_SampleRate = 44100;
}
RageSoundDriver_PulseAudio::~RageSoundDriver_PulseAudio()
@@ -31,312 +31,309 @@ RageSoundDriver_PulseAudio::~RageSoundDriver_PulseAudio()
pa_context_unref(m_PulseCtx);
pa_threaded_mainloop_stop(m_PulseMainLoop);
pa_threaded_mainloop_free(m_PulseMainLoop);
if(m_Error != NULL)
{
free(m_Error);
}
if(m_Error != NULL)
{
free(m_Error);
}
}
/* Initialization */
RString RageSoundDriver_PulseAudio::Init()
{
int error = 0;
int error = 0;
LOG->Trace("Pulse: pa_threaded_mainloop_new()...");
m_PulseMainLoop = pa_threaded_mainloop_new();
if(m_PulseMainLoop == NULL)
{
return "pa_threaded_mainloop_new() failed!";
}
LOG->Trace("Pulse: pa_threaded_mainloop_new()...");
m_PulseMainLoop = pa_threaded_mainloop_new();
if(m_PulseMainLoop == NULL)
{
return "pa_threaded_mainloop_new() failed!";
}
#ifdef PA_PROP_APPLICATION_NAME /* proplist available only since 0.9.11 */
pa_proplist *plist = pa_proplist_new();
pa_proplist_sets(plist, PA_PROP_APPLICATION_NAME, PACKAGE_NAME);
pa_proplist_sets(plist, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
pa_proplist_sets(plist, PA_PROP_MEDIA_ROLE, "game");
LOG->Trace("Pulse: pa_context_new_with_proplist()...");
m_PulseCtx = pa_context_new_with_proplist(
pa_threaded_mainloop_get_api(m_PulseMainLoop),
"StepMania", plist);
pa_proplist_free(plist);
if(m_PulseCtx == NULL)
{
return "pa_context_new_with_proplist() failed!";
}
pa_proplist *plist = pa_proplist_new();
pa_proplist_sets(plist, PA_PROP_APPLICATION_NAME, PACKAGE_NAME);
pa_proplist_sets(plist, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
pa_proplist_sets(plist, PA_PROP_MEDIA_ROLE, "game");
LOG->Trace("Pulse: pa_context_new_with_proplist()...");
m_PulseCtx = pa_context_new_with_proplist(
pa_threaded_mainloop_get_api(m_PulseMainLoop),
"StepMania", plist);
pa_proplist_free(plist);
if(m_PulseCtx == NULL)
{
return "pa_context_new_with_proplist() failed!";
}
#else
LOG->Trace("Pulse: pa_context_new()...");
m_PulseCtx = pa_context_new(
pa_threaded_mainloop_get_api(m_PulseMainLoop),
"Stepmania");
if(m_PulseCtx == NULL)
{
return "pa_context_new() failed!";
}
LOG->Trace("Pulse: pa_context_new()...");
m_PulseCtx = pa_context_new(
pa_threaded_mainloop_get_api(m_PulseMainLoop),
"Stepmania");
if(m_PulseCtx == NULL)
{
return "pa_context_new() failed!";
}
#endif
pa_context_set_state_callback(m_PulseCtx, StaticCtxStateCb, this);
pa_context_set_state_callback(m_PulseCtx, StaticCtxStateCb, this);
LOG->Trace("Pulse: pa_context_connect()...");
error = pa_context_connect(m_PulseCtx, NULL,
(pa_context_flags_t)0, NULL);
if(error < 0)
{
return ssprintf("pa_contect_connect(): %s",
pa_strerror(pa_context_errno(m_PulseCtx)));
}
LOG->Trace("Pulse: pa_context_connect()...");
error = pa_context_connect(m_PulseCtx, NULL, (pa_context_flags_t)0, NULL);
if(error < 0)
{
return ssprintf("pa_contect_connect(): %s",
pa_strerror(pa_context_errno(m_PulseCtx)));
}
LOG->Trace("Pulse: pa_threaded_mainloop_start()...");
error = pa_threaded_mainloop_start(m_PulseMainLoop);
if(error < 0)
{
return ssprintf("pa_threaded_mainloop_start() returned %i",
error);
}
LOG->Trace("Pulse: pa_threaded_mainloop_start()...");
error = pa_threaded_mainloop_start(m_PulseMainLoop);
if(error < 0)
{
return ssprintf("pa_threaded_mainloop_start() returned %i", error);
}
/* Create the decode thread, this will be needed for Mix(), that we
* will use as soon as a stream is ready. */
StartDecodeThread();
/* Create the decode thread, this will be needed for Mix(), that we
* will use as soon as a stream is ready. */
StartDecodeThread();
/* Wait for the pulseaudio stream to be ready before returning.
* An error may occur, if it appends, m_Error becomes non-NULL. */
m_Sem.Wait();
/* Wait for the pulseaudio stream to be ready before returning.
* An error may occur, if it appends, m_Error becomes non-NULL. */
m_Sem.Wait();
if(m_Error == NULL)
{
return "";
}
else
{
return m_Error;
}
if(m_Error == NULL)
{
return "";
}
else
{
return m_Error;
}
}
void RageSoundDriver_PulseAudio::m_InitStream(void)
{
int error;
pa_sample_spec ss;
pa_channel_map map;
int error;
pa_sample_spec ss;
pa_channel_map map;
/* init sample spec */
ss.format = PA_SAMPLE_S16LE;
ss.channels = 2;
ss.rate = PREFSMAN->m_iSoundPreferredSampleRate;
if(ss.rate == 0)
{
ss.rate = 44100;
}
/* init sample spec */
ss.format = PA_SAMPLE_S16LE;
ss.channels = 2;
ss.rate = PREFSMAN->m_iSoundPreferredSampleRate;
if(ss.rate == 0)
{
ss.rate = 44100;
}
/* init channel map */
pa_channel_map_init_stereo(&map);
/* init channel map */
pa_channel_map_init_stereo(&map);
/* check sample spec */
if(!pa_sample_spec_valid(&ss))
{
if(asprintf(&m_Error, "invalid sample spec!") == -1)
{
m_Error = NULL;
}
m_Sem.Post();
return;
}
/* check sample spec */
if(!pa_sample_spec_valid(&ss))
{
if(asprintf(&m_Error, "invalid sample spec!") == -1)
{
m_Error = NULL;
}
m_Sem.Post();
return;
}
/* log the used sample spec */
char specstring[PA_SAMPLE_SPEC_SNPRINT_MAX];
pa_sample_spec_snprint(specstring, sizeof(specstring), &ss);
LOG->Trace("Pulse: using sample spec: %s", specstring);
/* log the used sample spec */
char specstring[PA_SAMPLE_SPEC_SNPRINT_MAX];
pa_sample_spec_snprint(specstring, sizeof(specstring), &ss);
LOG->Trace("Pulse: using sample spec: %s", specstring);
/* create the stream */
LOG->Trace("Pulse: pa_stream_new()...");
m_PulseStream = pa_stream_new(m_PulseCtx, "Stepmania Audio", &ss, &map);
if(m_PulseStream == NULL)
{
if(asprintf(&m_Error, "pa_stream_new(): %s",
pa_strerror(pa_context_errno(m_PulseCtx))) == -1)
{
m_Error = NULL;
}
m_Sem.Post();
return;
}
/* create the stream */
LOG->Trace("Pulse: pa_stream_new()...");
m_PulseStream = pa_stream_new(m_PulseCtx, "Stepmania Audio", &ss, &map);
if(m_PulseStream == NULL)
{
if(asprintf(&m_Error, "pa_stream_new(): %s", pa_strerror(pa_context_errno(m_PulseCtx))) == -1)
{
m_Error = NULL;
}
m_Sem.Post();
return;
}
/* set the write callback, it will be called when the sound server
* needs data */
pa_stream_set_write_callback(m_PulseStream, StaticStreamWriteCb, this);
/* set the state callback, it will be called the the stream state will
* change */
pa_stream_set_state_callback(m_PulseStream, StaticStreamStateCb, this);
/* set the write callback, it will be called when the sound server
* needs data */
pa_stream_set_write_callback(m_PulseStream, StaticStreamWriteCb, this);
/* configure attributes of the stream */
pa_buffer_attr attr;
memset(&attr, 0x00, sizeof(attr));
/* set the state callback, it will be called the the stream state will
* change */
pa_stream_set_state_callback(m_PulseStream, StaticStreamStateCb, this);
/* tlength: Target length of the buffer.
*
* "The server tries to assure that at least tlength bytes are always
* available in the per-stream server-side playback buffer. It is
* recommended to set this to (uint32_t) -1, which will initialize
* this to a value that is deemed sensible by the server. However,
* this value will default to something like 2s, i.e. for applications
* that have specific latency requirements this value should be set to
* the maximum latency that the application can deal with."
*
* We don't want the default here, we want a small latency.
* We use pa_usec_to_bytes() to convert a latency to a buffer size.
*/
attr.tlength = pa_usec_to_bytes(20*PA_USEC_PER_MSEC, &ss);
/* configure attributes of the stream */
pa_buffer_attr attr;
memset(&attr, 0x00, sizeof(attr));
/* maxlength: Maximum length of the buffer
*
* "Setting this to (uint32_t) -1 will initialize this to the maximum
* value supported by server, which is recommended."
*
* (uint32_t)-1 is NOT working here, setting it to tlength*2, like
* openal-soft-pulseaudio does.
*/
attr.maxlength = attr.tlength*2;
/* tlength: Target length of the buffer.
*
* "The server tries to assure that at least tlength bytes are always
* available in the per-stream server-side playback buffer. It is
* recommended to set this to (uint32_t) -1, which will initialize
* this to a value that is deemed sensible by the server. However,
* this value will default to something like 2s, i.e. for applications
* that have specific latency requirements this value should be set to
* the maximum latency that the application can deal with."
*
* We don't want the default here, we want a small latency.
* We use pa_usec_to_bytes() to convert a latency to a buffer size.
*/
attr.tlength = pa_usec_to_bytes(20*PA_USEC_PER_MSEC, &ss);
/* minreq: Minimum request
*
* "The server does not request less than minreq bytes from the client,
* instead waits until the buffer is free enough to request more bytes
* at once. It is recommended to set this to (uint32_t) -1, which will
* initialize this to a value that is deemed sensible by the server."
*
* (uint32_t)-1 is NOT working here, setting it to 0, like
* openal-soft-pulseaudio does.
*/
attr.minreq = 0;
/* maxlength: Maximum length of the buffer
*
* "Setting this to (uint32_t) -1 will initialize this to the maximum
* value supported by server, which is recommended."
*
* (uint32_t)-1 is NOT working here, setting it to tlength*2, like
* openal-soft-pulseaudio does.
*/
attr.maxlength = attr.tlength*2;
/* prebuf: Pre-buffering
*
* "The server does not start with playback before at least prebuf
* bytes are available in the buffer. It is recommended to set this
* to (uint32_t) -1, which will initialize this to the same value as
* tlength"
*/
attr.prebuf = (uint32_t)-1;
/* minreq: Minimum request
*
* "The server does not request less than minreq bytes from the client,
* instead waits until the buffer is free enough to request more bytes
* at once. It is recommended to set this to (uint32_t) -1, which will
* initialize this to a value that is deemed sensible by the server."
*
* (uint32_t)-1 is NOT working here, setting it to 0, like
* openal-soft-pulseaudio does.
*/
attr.minreq = 0;
/* log the used target buffer length */
LOG->Trace("Pulse: using target buffer length of %i bytes",
attr.tlength);
/* prebuf: Pre-buffering
*
* "The server does not start with playback before at least prebuf
* bytes are available in the buffer. It is recommended to set this
* to (uint32_t) -1, which will initialize this to the same value as
* tlength"
*/
attr.prebuf = (uint32_t)-1;
/* connect the stream for playback */
LOG->Trace("Pulse: pa_stream_connect_playback()...");
error = pa_stream_connect_playback(m_PulseStream, NULL, &attr,
PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
if(error < 0)
{
if(asprintf(&m_Error, "pa_stream_connect_playback(): %s",
pa_strerror(pa_context_errno(m_PulseCtx))) == -1)
{
m_Error = NULL;
}
m_Sem.Post();
return;
}
/* log the used target buffer length */
LOG->Trace("Pulse: using target buffer length of %i bytes", attr.tlength);
m_SampleRate = ss.rate;
/* connect the stream for playback */
LOG->Trace("Pulse: pa_stream_connect_playback()...");
error = pa_stream_connect_playback(m_PulseStream, NULL, &attr,
PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
if(error < 0)
{
if(asprintf(&m_Error, "pa_stream_connect_playback(): %s",
pa_strerror(pa_context_errno(m_PulseCtx))) == -1)
{
m_Error = NULL;
}
m_Sem.Post();
return;
}
m_SampleRate = ss.rate;
}
void RageSoundDriver_PulseAudio::CtxStateCb(pa_context *c)
{
switch (pa_context_get_state(m_PulseCtx))
{
case PA_CONTEXT_CONNECTING:
LOG->Trace("Pulse: Context connecting...");
break;
case PA_CONTEXT_AUTHORIZING:
LOG->Trace("Pulse: Context authorizing...");
break;
case PA_CONTEXT_SETTING_NAME:
LOG->Trace("Pulse: Context setting name...");
break;
case PA_CONTEXT_READY:
LOG->Trace("Pulse: Context ready now.");
m_InitStream();
break;
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
if(asprintf(&m_Error, "context connection failed: %s",
pa_strerror(pa_context_errno(m_PulseCtx)))
== -1)
{
m_Error = NULL;
}
m_Sem.Post();
return;
break;
}
switch (pa_context_get_state(m_PulseCtx))
{
case PA_CONTEXT_CONNECTING:
LOG->Trace("Pulse: Context connecting...");
break;
case PA_CONTEXT_AUTHORIZING:
LOG->Trace("Pulse: Context authorizing...");
break;
case PA_CONTEXT_SETTING_NAME:
LOG->Trace("Pulse: Context setting name...");
break;
case PA_CONTEXT_READY:
LOG->Trace("Pulse: Context ready now.");
m_InitStream();
break;
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
if(asprintf(&m_Error, "context connection failed: %s", pa_strerror(pa_context_errno(m_PulseCtx))) == -1)
{
m_Error = NULL;
}
m_Sem.Post();
return;
break;
}
}
void RageSoundDriver_PulseAudio::StreamStateCb(pa_stream *s)
{
switch(pa_stream_get_state(m_PulseStream))
{
case PA_STREAM_CREATING:
LOG->Trace("Pulse: Stream creating...");
break;
case PA_STREAM_READY:
LOG->Trace("Pulse: Stream ready now/");
m_Sem.Post();
return;
break;
case PA_STREAM_UNCONNECTED:
case PA_STREAM_TERMINATED:
case PA_STREAM_FAILED:
if(asprintf(&m_Error, "stream connection failed: %s",
pa_strerror(pa_context_errno(m_PulseCtx)))
== -1)
{
}
m_Sem.Post();
return;
break;
}
switch(pa_stream_get_state(m_PulseStream))
{
case PA_STREAM_CREATING:
LOG->Trace("Pulse: Stream creating...");
break;
case PA_STREAM_READY:
LOG->Trace("Pulse: Stream ready now/");
m_Sem.Post();
return;
break;
case PA_STREAM_UNCONNECTED:
case PA_STREAM_TERMINATED:
case PA_STREAM_FAILED:
if(asprintf(&m_Error, "stream connection failed: %s",
pa_strerror(pa_context_errno(m_PulseCtx))) == -1)
{
}
m_Sem.Post();
return;
break;
}
}
int64_t RageSoundDriver_PulseAudio::GetPosition() const
{
return m_LastPosition;
return m_LastPosition;
}
void RageSoundDriver_PulseAudio::StreamWriteCb(pa_stream *s, size_t length)
{
#if PA_API_VERSION <= 11
/* We have to multiply the requested length by 2 on 0.9.10
* maybe the requested length is given in frames instead of bytes */
length *= 2;
/* We have to multiply the requested length by 2 on 0.9.10
* maybe the requested length is given in frames instead of bytes */
length *= 2;
#endif
size_t nbframes = length / sizeof(int16_t); /* we use 16-bit frames */
int16_t buf[nbframes];
int64_t pos1 = m_LastPosition;
int64_t pos2 = pos1 + nbframes/2; /* Mix() position in stereo frames */
this->Mix( buf, pos2-pos1, pos1, pos2);
if(pa_stream_write(m_PulseStream, buf, length, NULL, 0, PA_SEEK_RELATIVE) < 0)
{
RageException::Throw("Pulse: pa_stream_write()");
}
m_LastPosition = pos2;
size_t nbframes = length / sizeof(int16_t); /* we use 16-bit frames */
int16_t buf[nbframes];
int64_t pos1 = m_LastPosition;
int64_t pos2 = pos1 + nbframes/2; /* Mix() position in stereo frames */
this->Mix( buf, pos2-pos1, pos1, pos2);
if(pa_stream_write(m_PulseStream, buf, length, NULL, 0, PA_SEEK_RELATIVE) < 0)
{
RageException::Throw("Pulse: pa_stream_write()");
}
m_LastPosition = pos2;
}
/* Static wrappers, because pulseaudio is a C API, it uses callbacks.
* So we have to write wrappers that will call our objects callbacks. */
void RageSoundDriver_PulseAudio::StaticCtxStateCb(pa_context *c, void *user)
{
RageSoundDriver_PulseAudio *obj = (RageSoundDriver_PulseAudio*)user;
obj->CtxStateCb(c);
RageSoundDriver_PulseAudio *obj = (RageSoundDriver_PulseAudio*)user;
obj->CtxStateCb(c);
}
void RageSoundDriver_PulseAudio::StaticStreamStateCb(pa_stream *s, void *user)
{
RageSoundDriver_PulseAudio *obj = (RageSoundDriver_PulseAudio*)user;
obj->StreamStateCb(s);
RageSoundDriver_PulseAudio *obj = (RageSoundDriver_PulseAudio*)user;
obj->StreamStateCb(s);
}
void RageSoundDriver_PulseAudio::StaticStreamWriteCb(pa_stream *s,
size_t length, void *user)
void RageSoundDriver_PulseAudio::StaticStreamWriteCb(pa_stream *s, size_t length, void *user)
{
RageSoundDriver_PulseAudio *obj = (RageSoundDriver_PulseAudio*)user;
obj->StreamWriteCb(s, length);
RageSoundDriver_PulseAudio *obj = (RageSoundDriver_PulseAudio*)user;
obj->StreamWriteCb(s, length);
}
/*
@@ -362,4 +359,4 @@ void RageSoundDriver_PulseAudio::StaticStreamWriteCb(pa_stream *s,
* 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.
*/
*/
@@ -6,38 +6,37 @@
#include "RageSoundDriver.h"
#include <pulse/pulseaudio.h>
class RageSoundDriver_PulseAudio: public RageSoundDriver
class RageSoundDriver_PulseAudio : public RageSoundDriver
{
public:
RageSoundDriver_PulseAudio();
virtual ~RageSoundDriver_PulseAudio();
RageSoundDriver_PulseAudio();
virtual ~RageSoundDriver_PulseAudio();
RString Init();
RString Init();
inline int64_t GetPosition() const;
inline int GetSampleRate() const { return m_SampleRate; };
inline int64_t GetPosition() const;
inline int GetSampleRate() const { return m_SampleRate; };
protected:
int64_t m_LastPosition;
int m_SampleRate;
char *m_Error;
int64_t m_LastPosition;
int m_SampleRate;
char *m_Error;
void m_InitStream();
RageSemaphore m_Sem;
void m_InitStream();
RageSemaphore m_Sem;
pa_threaded_mainloop *m_PulseMainLoop;
pa_context *m_PulseCtx;
pa_stream *m_PulseStream;
pa_threaded_mainloop *m_PulseMainLoop;
pa_context *m_PulseCtx;
pa_stream *m_PulseStream;
public:
void CtxStateCb(pa_context *c);
void StreamStateCb(pa_stream *s);
void StreamWriteCb(pa_stream *s, size_t length);
void CtxStateCb(pa_context *c);
void StreamStateCb(pa_stream *s);
void StreamWriteCb(pa_stream *s, size_t length);
static void StaticCtxStateCb(pa_context *c, void *user);
static void StaticStreamStateCb(pa_stream *s, void *user);
static void StaticStreamWriteCb(pa_stream *s,
size_t length, void *user);
static void StaticCtxStateCb(pa_context *c, void *user);
static void StaticStreamStateCb(pa_stream *s, void *user);
static void StaticStreamWriteCb(pa_stream *s, size_t length, void *user);
};
#endif /* RAGE_SOUND_PULSEAUDIO_H */