Fix indentation to match everything else.
This commit is contained in:
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user