// PulseAudio I/O Callbacks //{{{
static void stream_write_callback( pa_stream* stream, size_t len, void* pdata ) //{{{
{
	ALCdevice* Device = pdata;
	pulse_data* data = Device->ExtraData;

	while ( len > 0 )
	{
		size_t newlen = len;
		void* buf;
		pa_free_cb_t free_func = NULL;

#if PA_CHECK_VERSION(0,9,16)

		if ( !ppa_stream_begin_write ||
		     ppa_stream_begin_write( stream, &buf, &newlen ) < 0 )
#endif
		{
			buf = ppa_xmalloc( newlen );
			free_func = ppa_xfree;
		}

		aluMixData( Device, buf, newlen / data->frame_size );
		ppa_stream_write( stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE );
		len -= newlen;
	}
} //}}}
static ALCboolean pulse_open( ALCdevice* device, const ALCchar* device_name ) //{{{
{
	pulse_data* data = ppa_xmalloc( sizeof( pulse_data ) );
	memset( data, 0, sizeof( *data ) );

	if ( !( data->loop = ppa_threaded_mainloop_new() ) )
	{
		AL_PRINT( "pa_threaded_mainloop_new() failed!\n" );
		goto out;
	}

	if ( ppa_threaded_mainloop_start( data->loop ) < 0 )
	{
		AL_PRINT( "pa_threaded_mainloop_start() failed\n" );
		goto out;
	}

	ppa_threaded_mainloop_lock( data->loop );
	device->ExtraData = data;

	data->context = connect_context( data->loop );

	if ( !data->context )
	{
		ppa_threaded_mainloop_unlock( data->loop );
		goto out;
	}

	ppa_context_set_state_callback( data->context, context_state_callback2, device );

	device->szDeviceName = strdup( device_name );

	ppa_threaded_mainloop_unlock( data->loop );
	return ALC_TRUE;

out:

	if ( data->loop )
	{
		ppa_threaded_mainloop_stop( data->loop );
		ppa_threaded_mainloop_free( data->loop );
	}

	device->ExtraData = NULL;
	ppa_xfree( data );
	return ALC_FALSE;
} //}}}
Example #3
0
static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{{
{
    pulse_data *data = ppa_xmalloc(sizeof(pulse_data));
    pa_context_state_t state;

    memset(data, 0, sizeof(*data));

    if(ppa_get_binary_name(data->path_name, sizeof(data->path_name)))
        data->context_name = ppa_path_get_filename(data->path_name);
    else
        data->context_name = "OpenAL Soft";

    if(!(data->loop = ppa_threaded_mainloop_new()))
    {
        AL_PRINT("pa_threaded_mainloop_new() failed!\n");
        goto out;
    }

    if(ppa_threaded_mainloop_start(data->loop) < 0)
    {
        AL_PRINT("pa_threaded_mainloop_start() failed\n");
        goto out;
    }

    ppa_threaded_mainloop_lock(data->loop);
    device->ExtraData = data;

    data->context = ppa_context_new(ppa_threaded_mainloop_get_api(data->loop), data->context_name);
    if(!data->context)
    {
        AL_PRINT("pa_context_new() failed\n");

        ppa_threaded_mainloop_unlock(data->loop);
        goto out;
    }

    ppa_context_set_state_callback(data->context, context_state_callback, device);

    if(ppa_context_connect(data->context, NULL, pulse_ctx_flags, NULL) < 0)
    {
        AL_PRINT("Context did not connect: %s\n",
                 ppa_strerror(ppa_context_errno(data->context)));

        ppa_context_unref(data->context);
        data->context = NULL;

        ppa_threaded_mainloop_unlock(data->loop);
        goto out;
    }

    while((state=ppa_context_get_state(data->context)) != PA_CONTEXT_READY)
    {
        if(!PA_CONTEXT_IS_GOOD(state))
        {
            int err = ppa_context_errno(data->context);
            if(err != PA_ERR_CONNECTIONREFUSED)
                AL_PRINT("Context did not get ready: %s\n", ppa_strerror(err));

            ppa_context_unref(data->context);
            data->context = NULL;

            ppa_threaded_mainloop_unlock(data->loop);
            goto out;
        }

        ppa_threaded_mainloop_wait(data->loop);
    }
    ppa_context_set_state_callback(data->context, context_state_callback2, device);

    device->szDeviceName = strdup(device_name);

    ppa_threaded_mainloop_unlock(data->loop);
    return ALC_TRUE;

out:
    if(data->loop)
    {
        ppa_threaded_mainloop_stop(data->loop);
        ppa_threaded_mainloop_free(data->loop);
    }

    device->ExtraData = NULL;
    ppa_xfree(data);
    return ALC_FALSE;
} //}}}