Skip to content

Commit

Permalink
Pulseaudio: Add function to handle Pulseaudio pa_operation (#924)
Browse files Browse the repository at this point in the history
Consolidate pa_operation handling into a single function to make
sure that all cases are handled consistently. Ensure that mainloop is locked when using pa_threaded_mainloop_wait.
  • Loading branch information
illuusio authored Oct 3, 2024
1 parent c121482 commit c57b762
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 73 deletions.
52 changes: 26 additions & 26 deletions src/hostapi/pulseaudio/pa_linux_pulseaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,13 @@
*/


#include <string.h> /* strlen() */

#include "pa_linux_pulseaudio_cb_internal.h"
#include "pa_linux_pulseaudio_block_internal.h"

/* PulseAudio headers */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pulse/pulseaudio.h>

/* This is used to identify process name for PulseAudio. */
Expand Down Expand Up @@ -650,12 +649,14 @@ PaError PaPulseAudio_Initialize( PaUtilHostApiRepresentation ** hostApi,
PaPulseAudio_ServerInfoCb,
pulseaudioHostApi );

while( pa_operation_get_state( pulseaudioOperation ) == PA_OPERATION_RUNNING )
{
pa_threaded_mainloop_wait( pulseaudioHostApi->mainloop );
}
PaPulseAudio_UnLock( pulseaudioHostApi->mainloop );
lockTaken = 0;

pa_operation_unref( pulseaudioOperation );
PaPulseAudio_ReleaseOperation( pulseaudioHostApi,
&pulseaudioOperation );

PaPulseAudio_Lock( pulseaudioHostApi->mainloop );
lockTaken = 1;

/* Add the "Default" sink at index 0 */
if( _PaPulseAudio_AddAudioDevice( pulseaudioHostApi,
Expand Down Expand Up @@ -701,25 +702,29 @@ PaError PaPulseAudio_Initialize( PaUtilHostApiRepresentation ** hostApi,
PaPulseAudio_SinkListCb,
pulseaudioHostApi );

while( pa_operation_get_state( pulseaudioOperation ) == PA_OPERATION_RUNNING )
{
pa_threaded_mainloop_wait( pulseaudioHostApi->mainloop );
}
PaPulseAudio_UnLock( pulseaudioHostApi->mainloop );
lockTaken = 0;

PaPulseAudio_ReleaseOperation( pulseaudioHostApi,
&pulseaudioOperation );

pa_operation_unref( pulseaudioOperation );
PaPulseAudio_Lock( pulseaudioHostApi->mainloop );
lockTaken = 1;

/* List PulseAudio sources. If found callback: PaPulseAudio_SourceListCb */
pulseaudioOperation =
pa_context_get_source_info_list( pulseaudioHostApi->context,
PaPulseAudio_SourceListCb,
pulseaudioHostApi );

while( pa_operation_get_state( pulseaudioOperation ) == PA_OPERATION_RUNNING )
{
pa_threaded_mainloop_wait( pulseaudioHostApi->mainloop );
}
PaPulseAudio_UnLock( pulseaudioHostApi->mainloop );
lockTaken = 0;

pa_operation_unref( pulseaudioOperation );
PaPulseAudio_ReleaseOperation( pulseaudioHostApi,
&pulseaudioOperation );

PaPulseAudio_Lock( pulseaudioHostApi->mainloop );
lockTaken = 1;

(*hostApi)->info.deviceCount = pulseaudioHostApi->deviceCount;

Expand Down Expand Up @@ -1461,11 +1466,8 @@ PaError PaPulseAudio_RenameSource( PaStream *s, const char *streamName )
op = pa_stream_set_name( stream->inputStream, streamName, RenameStreamCb, stream );
PaPulseAudio_UnLock( stream->mainloop );

/* Wait for completion. */
while (pa_operation_get_state( op ) == PA_OPERATION_RUNNING)
{
pa_threaded_mainloop_wait( stream->mainloop );
}
PaPulseAudio_ReleaseOperation( stream->hostapi,
&op );

return result;
}
Expand Down Expand Up @@ -1498,10 +1500,8 @@ PaError PaPulseAudio_RenameSink( PaStream *s, const char *streamName )
PaPulseAudio_UnLock( stream->mainloop );

/* Wait for completion. */
while (pa_operation_get_state( op ) == PA_OPERATION_RUNNING)
{
pa_threaded_mainloop_wait( stream->mainloop );
}
PaPulseAudio_ReleaseOperation( stream->hostapi,
&op );

return result;
}
98 changes: 54 additions & 44 deletions src/hostapi/pulseaudio/pa_linux_pulseaudio_cb.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,50 @@ int PaPulseAudio_updateTimeInfo( pa_stream * s,
return 0;
}

/* Release pa_operation always same way */
void PaPulseAudio_ReleaseOperation(PaPulseAudio_HostApiRepresentation *hostapi,
pa_operation **operation)
{
unsigned int waitOperation = 1000;
pa_operation *localOperation = (*operation);
pa_operation_state_t localOperationState = PA_OPERATION_RUNNING;

// As mainly operation is done when running locally
// done after 1-3 then 1000 is enough to wait if
// something goes wrong

while( waitOperation > 0 )
{
PaPulseAudio_Lock( hostapi->mainloop );
pa_threaded_mainloop_wait( hostapi->mainloop );
PaPulseAudio_UnLock( hostapi->mainloop );

localOperationState = pa_operation_get_state( localOperation );

// No wait if operation have been DONE or CANCELLED
if( localOperationState != PA_OPERATION_RUNNING)
{
break;
}

waitOperation --;

usleep( 1000 );
}

// No wait if operation have been DONE or CANCELLED
if( localOperationState == PA_OPERATION_RUNNING)
{
PA_DEBUG( ( "Portaudio %s: Operation still running %d!\n",
__FUNCTION__, localOperationState ) );
}

PaPulseAudio_Lock( hostapi->mainloop );
pa_operation_unref( localOperation );
operation = NULL;
PaPulseAudio_UnLock( hostapi->mainloop );
}


/* locks the Pulse Main loop when not called from it */
void PaPulseAudio_Lock( pa_threaded_mainloop *mainloop )
Expand Down Expand Up @@ -488,22 +532,10 @@ PaError PaPulseAudio_CloseStreamCb( PaStream * s )
stream );
PaPulseAudio_UnLock( stream->mainloop );

while( pa_operation_get_state( pulseaudioOperation ) == PA_OPERATION_RUNNING )
{
pa_threaded_mainloop_wait( pulseaudioHostApi->mainloop );
waitLoop ++;

if(waitLoop > 256)
{
break;
}
}

waitLoop = 0;
PaPulseAudio_ReleaseOperation( pulseaudioHostApi,
&pulseaudioOperation );

PaPulseAudio_Lock(stream->mainloop);
pa_operation_unref( pulseaudioOperation );
pulseaudioOperation = NULL;

pa_stream_disconnect( stream->outputStream );
PaPulseAudio_UnLock( stream->mainloop );
Expand All @@ -520,22 +552,10 @@ PaError PaPulseAudio_CloseStreamCb( PaStream * s )
stream );
PaPulseAudio_UnLock( stream->mainloop );

while( pa_operation_get_state( pulseaudioOperation ) == PA_OPERATION_RUNNING )
{
pa_threaded_mainloop_wait( pulseaudioHostApi->mainloop );
waitLoop ++;

if(waitLoop > 256)
{
break;
}
}

waitLoop = 0;
PaPulseAudio_ReleaseOperation( pulseaudioHostApi,
&pulseaudioOperation );

PaPulseAudio_Lock( stream->mainloop );
pa_operation_unref( pulseaudioOperation );
pulseaudioOperation = NULL;

/* Then we disconnect stream and wait for
* Termination
Expand Down Expand Up @@ -641,7 +661,6 @@ PaError PaPulseAudio_StartStreamCb( PaStream * s )
PaPulseAudio_HostApiRepresentation *pulseaudioHostApi = stream->hostapi;
const char *pulseaudioName = NULL;
pa_operation *pulseaudioOperation = NULL;
int waitLoop = 0;
unsigned int pulseaudioReqFrameSize = stream->suggestedLatencyUSecs;

stream->isActive = 0;
Expand Down Expand Up @@ -769,13 +788,8 @@ PaError PaPulseAudio_StartStreamCb( PaStream * s )
stream );
PaPulseAudio_UnLock( pulseaudioHostApi->mainloop );

while( pa_operation_get_state( pulseaudioOperation ) == PA_OPERATION_RUNNING)
{
pa_threaded_mainloop_wait( pulseaudioHostApi->mainloop );
}

pa_operation_unref( pulseaudioOperation );
pulseaudioOperation = NULL;
PaPulseAudio_ReleaseOperation( pulseaudioHostApi,
&pulseaudioOperation );
}
else
{
Expand Down Expand Up @@ -919,14 +933,10 @@ static PaError RequestStop( PaPulseAudio_Stream * stream,
PaPulseAudio_CorkSuccessCb,
stream );

while( pa_operation_get_state( pulseaudioOperation ) == PA_OPERATION_RUNNING )
{
pa_threaded_mainloop_wait( pulseaudioHostApi->mainloop );
}

pa_operation_unref( pulseaudioOperation );

pulseaudioOperation = NULL;
PaPulseAudio_UnLock( pulseaudioHostApi->mainloop );
PaPulseAudio_ReleaseOperation( pulseaudioHostApi,
&pulseaudioOperation );
PaPulseAudio_Lock( pulseaudioHostApi->mainloop );
}

requeststop_error:
Expand Down
8 changes: 5 additions & 3 deletions src/hostapi/pulseaudio/pa_linux_pulseaudio_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,14 @@ PaPulseAudio_Stream;
return errorCode; \
} \
} \
if( !pastream->isActive || pastream->isStopped ) \
if( !(pastream)->isActive || (pastream)->isStopped ) \
{ \
return paStreamIsStopped; \
return paStreamIsStopped; \
}

void PaPulseAudio_ReleaseOperation(PaPulseAudio_HostApiRepresentation *hostapi,
pa_operation **pulseaudioOperation);

void PaPulseAudio_Lock( pa_threaded_mainloop *mainloop );

void PaPulseAudio_UnLock( pa_threaded_mainloop *mainloop );
Expand All @@ -225,7 +228,6 @@ PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
PaStreamCallback * streamCallback,
void *userData );


PaError IsStreamStopped( PaStream * s );
PaError IsStreamActive( PaStream * stream );

Expand Down

0 comments on commit c57b762

Please sign in to comment.