Exemplo n.º 1
0
void QPulseAudioThread::initialize_callbacks ( QPulseAudioThread * pulseThread )
{
    pa_operation * op;
    pa_operation_unref
    ( pa_context_get_source_info_list ( context, pa_source_info_callback, pulseThread ) );

    //pa_operation_unref(pa_context_get_server_info(&c, server_info_callback, this));
    //pa_operation_unref(pa_context_get_sink_info_list(&c, sink_info_callback, this));
    //pa_operation_unref(pa_context_get_source_info_list(&c, source_info_callback, this));
    //pa_operation_unref(pa_context_get_module_info_list(&c, module_info_callback, this));
    //pa_operation_unref(pa_context_get_client_info_list(&c, client_info_callback, this));
    //pa_operation_unref(pa_context_get_sink_input_info_list(&c, sink_input_info_callback, this));
    //pa_operation_unref(pa_context_get_source_output_info_list(&c, source_output_info_callback, this));
    //pa_operation_unref(pa_context_get_sample_info_list(&c, sample_info_callback, this));


    //pa_context_set_drain
    pa_context_set_subscribe_callback ( context, subscribe_callback, pulseThread );

    if ( op = pa_context_subscribe ( context, ( enum pa_subscription_mask )
                                     PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, NULL, NULL ) ) {
        pa_operation_unref ( op );
    } else {
        qDebug() << "null op returned on subscribe";
    }

}
Exemplo n.º 2
0
void QPulseAudioEngine::updateDevices()
{
    lock();

    // Get default input and output devices
    pa_operation *operation = pa_context_get_server_info(m_context, serverInfoCallback, this);
    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(m_mainLoop);
    pa_operation_unref(operation);

    // Get output devices
    operation = pa_context_get_sink_info_list(m_context, sinkInfoCallback, this);
    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(m_mainLoop);
    pa_operation_unref(operation);

    // Get input devices
    operation = pa_context_get_source_info_list(m_context, sourceInfoCallback, this);
    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(m_mainLoop);
    pa_operation_unref(operation);

    unlock();

    // Swap the default output to index 0
    m_sinks.removeOne(m_defaultSink);
    m_sinks.prepend(m_defaultSink);

    // Swap the default input to index 0
    m_sources.removeOne(m_defaultSource);
    m_sources.prepend(m_defaultSource);
}
Exemplo n.º 3
0
static void on_pulse_context_state_change(pa_context *pa_context, AudioListContext *context)
{
    gint error;
    error = pa_context_errno(pa_context);
    if (error) {
        g_warning("PulseAudio: error: %s", pa_strerror(error));
    }
    switch (pa_context_get_state(pa_context)) {
    case PA_CONTEXT_READY:
        pa_context_get_source_info_list(pa_context, (pa_source_info_cb_t) source_info_iterator, context);
        break;
    case PA_CONTEXT_FAILED:
        g_warning("PulseAudio: failed to connect to daemon");
        finish_pa_list(context);
        break;
    case PA_CONTEXT_TERMINATED:
        break;
    case PA_CONTEXT_UNCONNECTED:
        break;
    case PA_CONTEXT_CONNECTING:
        break;
    case PA_CONTEXT_AUTHORIZING:
        break;
    case PA_CONTEXT_SETTING_NAME:
        break;
    default:
        break;
    }
}
Exemplo n.º 4
0
/*
 * enumerate input/output devices
 */
static void pulse_enumerate_devices(obs_properties_t props, bool input)
{
	pa_context *c;
	pa_operation *op;
	pa_threaded_mainloop *m = pa_threaded_mainloop_new();
	struct pulse_enumerate e;

	e.mainloop = m;
	e.devices = obs_properties_add_list(props, "device_id", "Device",
		OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
	e.input = input;

	pa_threaded_mainloop_start(m);
	c = pulse_context_create(m);

	if (pulse_context_connect(m, c) < 0)
		goto fail;

	pa_threaded_mainloop_lock(m);

	op = pa_context_get_source_info_list(c, pulse_source_info, (void *) &e);
	while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
		pa_threaded_mainloop_wait(m);
	pa_operation_unref(op);

	pa_threaded_mainloop_unlock(m);

	pa_context_disconnect(c);
fail:
	pa_context_unref(c);
	pa_threaded_mainloop_stop(m);
	pa_threaded_mainloop_free(m);
}
Exemplo n.º 5
0
static bool set_mic_mute_cb(LSHandle *handle, LSMessage *message, void *user_data)
{
	struct audio_service *service = user_data;
	const char *payload;
	jvalue_ref parsed_obj = NULL;
	struct luna_service_req_data *req;
	pa_operation *op;

	if (!service->context_initialized) {
		luna_service_message_reply_custom_error(handle, message, "Not yet initialized");
		return true;
	}

	payload = LSMessageGetPayload(message);
	parsed_obj = luna_service_message_parse_and_validate(payload);
	if (jis_null(parsed_obj)) {
		luna_service_message_reply_error_bad_json(handle, message);
		goto cleanup;
	}

	service->mic_mute = luna_service_message_get_boolean(parsed_obj, "micMute", service->mic_mute);

	req = luna_service_req_data_new(handle, message);
	req->user_data = service;

	op = pa_context_get_source_info_list(service->context, mm_sourceinfo_cb, req);
	pa_operation_unref(op);

cleanup:
	if (!jis_null(parsed_obj))
		j_release(&parsed_obj);

	return true;
}
Exemplo n.º 6
0
void _cb_state_changed(pa_context *context, void *userdata) {
    callback_t *callback = (callback_t*)userdata;
    pa_context_state_t state = pa_context_get_state(context);
    PACMIXER_LOG("B:server state changed to %d", state);
    switch(state) {
        case PA_CONTEXT_READY:
            pa_context_set_subscribe_callback(context, _cb_event, callback);
            pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_ALL, NULL, NULL);
            pa_context_get_sink_input_info_list(context, _cb_sink_input, callback);
            pa_context_get_sink_info_list(context, _cb_sink, callback);
            pa_context_get_source_info_list(context, _cb_source, callback);
            pa_context_get_source_output_info_list(context, _cb_source_output, callback);
            pa_context_get_card_info_list(context, _cb_card, callback);
            pa_context_get_server_info(context, _cb_server, callback);
            ((tstate_callback_func)(callback->state))(callback->self, S_CAME);
            break;
        case PA_CONTEXT_FAILED:
        case PA_CONTEXT_TERMINATED:
            pa_context_unref(context);
            ((tstate_callback_func)(callback->state))(callback->self, S_GONE);
            break;
        default:
            break;
    }
}
Exemplo n.º 7
0
static int pa_get_devicelist(AudioDeviceInfoList& input)
{
	pa_mainloop *pa_ml;
	pa_mainloop_api *pa_mlapi;
	pa_operation *pa_op;
	pa_context *pa_ctx;

	int state = 0;
	int pa_ready = 0;

	pa_ml = pa_mainloop_new();
	pa_mlapi = pa_mainloop_get_api(pa_ml);
	pa_ctx = pa_context_new(pa_mlapi, "USBqemu-devicelist");

	pa_context_connect(pa_ctx, NULL, PA_CONTEXT_NOFLAGS, NULL);

	pa_context_set_state_callback(pa_ctx, pa_context_state_cb, &pa_ready);

	for (;;) {

		if (pa_ready == 0)
		{
			pa_mainloop_iterate(pa_ml, 1, NULL);
			continue;
		}

		// Connection failed
		if (pa_ready == 2)
		{
			pa_context_disconnect(pa_ctx);
			pa_context_unref(pa_ctx);
			pa_mainloop_free(pa_ml);
			return -1;
		}

		switch (state)
		{
			case 0:
				pa_op = pa_context_get_source_info_list(pa_ctx,
						pa_sourcelist_cb,
						&input);
				state++;
				break;
			case 1:
				if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE)
				{
					pa_operation_unref(pa_op);
					pa_context_disconnect(pa_ctx);
					pa_context_unref(pa_ctx);
					pa_mainloop_free(pa_ml);
					return 0;
				}
				break;
			default:
				return -1;
		}
		pa_mainloop_iterate(pa_ml, 1, NULL);
	}
}
Exemplo n.º 8
0
static void cm_sinkinfo_cb(pa_context *context, const pa_sink_info *info, int is_last, void *user_data)
{
	struct luna_service_req_data *req = user_data;
	struct audio_service *service = req->user_data;
	pa_sink_port_info *earpiece = NULL, *speaker = NULL, *headphones = NULL;
	pa_sink_port_info *highest = NULL, *preferred = NULL;
	pa_operation *op;
	int i;

	for (i = 0; i < info->n_ports; i++) {
		if (!highest || info->ports[i]->priority > highest->priority) {
			if (info->ports[i]->available != PA_PORT_AVAILABLE_NO)
				highest = info->ports[i];
		}
		if (!strcmp(info->ports[i]->name, "output-earpiece"))
			earpiece = info->ports[i];
		if (!strcmp(info->ports[i]->name, "output-speaker"))
			speaker = info->ports[i];
		if (!strcmp(info->ports[i]->name, "output-wired_headset") &&
				info->ports[i]->available != PA_PORT_AVAILABLE_NO)
			headphones = info->ports[i];
		if (!strcmp(info->ports[i]->name, "output-wired_headphone") &&
				info->ports[i]->available != PA_PORT_AVAILABLE_NO)
			headphones = info->ports[i];
	}

	if (is_last && !earpiece) {
		finish_set_call_mode(false, user_data);
		return;
	}

	if (!earpiece)
		return; /* Not the right sink */

	/* TODO: When on ringtone and headphones are plugged in, people want output
	   through *both* headphones and speaker, but when on call with speaker mode,
	   people want *just* speaker, not including headphones. */
	if (service->speaker_mode)
		preferred = speaker;
	else if (service->in_call)
		preferred = headphones ? headphones : earpiece;

	if (!preferred)
		preferred = highest;

	if (preferred && preferred != info->active_port) {
		op = pa_context_set_sink_port_by_name(service->context, info->name, preferred->name, cm_sink_port_set_cb, req);
		pa_operation_unref(op);
	}
	else {
		op = pa_context_get_source_info_list(context, cm_sourceinfo_cb, user_data);
		pa_operation_unref(op);
	}
}
Exemplo n.º 9
0
void PulseAudioSystem::query() {
	bSourceDone=bSinkDone=bServerDone = false;
	qhInput.clear();
	qhOutput.clear();
	qhEchoMap.clear();
	qhSpecMap.clear();
	qhChanMap.clear();
	qhInput.insert(QString(), tr("Default Input"));
	qhOutput.insert(QString(), tr("Default Output"));
	pa_operation_unref(pa_context_get_server_info(pacContext, server_callback, this));
	pa_operation_unref(pa_context_get_sink_info_list(pacContext, sink_callback, this));
	pa_operation_unref(pa_context_get_source_info_list(pacContext, source_callback, this));
	wakeup();
}
void context_state_cb(pa_context *c, void *userdata) {

    switch (pa_context_get_state(c)) {
    case PA_CONTEXT_UNCONNECTED:
    case PA_CONTEXT_CONNECTING:
    case PA_CONTEXT_AUTHORIZING:
    case PA_CONTEXT_SETTING_NAME:
	break;

    case PA_CONTEXT_READY: {
	pa_operation *o;

	if (!(o = pa_context_get_source_info_list(c,
						  source_cb,
						  NULL
						  ))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	if (!(o = pa_context_get_sink_info_list(c,
						sink_cb,
						NULL
						))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	pa_context_set_subscribe_callback(c, subscribe_cb, NULL);

	if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)
				       (PA_SUBSCRIPTION_MASK_SINK|
					PA_SUBSCRIPTION_MASK_SOURCE), NULL, NULL))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	break;
    }

    case PA_CONTEXT_FAILED:
    case PA_CONTEXT_TERMINATED:
    default:
	return;
    }
}
Exemplo n.º 11
0
Arquivo: pulse.c Projeto: IAPark/vlc
static int Open (vlc_object_t *obj)
{
    services_discovery_t *sd = (services_discovery_t *)obj;
    pa_operation *op;
    pa_context *ctx;

    services_discovery_sys_t *sys = malloc (sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    ctx = vlc_pa_connect (obj, &sys->mainloop);
    if (ctx == NULL)
    {
        free (sys);
        return VLC_EGENERIC;
    }

    sd->p_sys = sys;
    sd->description = _("Audio capture");
    sys->context = ctx;
    sys->root = NULL;

    /* Subscribe for source events */
    const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SOURCE;
    pa_threaded_mainloop_lock (sys->mainloop);
    pa_context_set_subscribe_callback (ctx, ContextCallback, sd);
    op = pa_context_subscribe (ctx, mask, NULL, NULL);
    if (likely(op != NULL))
        pa_operation_unref (op);

    /* Enumerate existing sources */
    op = pa_context_get_source_info_list (ctx, SourceCallback, sd);
    if (likely(op != NULL))
    {
        //while (pa_operation_get_state (op) == PA_OPERATION_RUNNING)
        //    pa_threaded_mainloop_wait (sys->mainloop);
        pa_operation_unref (op);
    }
    pa_threaded_mainloop_unlock (sys->mainloop);
    return VLC_SUCCESS;
/*
error:
    pa_threaded_mainloop_unlock (sys->mainloop);
    vlc_pa_disconnect (obj, ctx, sys->mainloop);
    free (sys);
    return VLC_EGENERIC;*/
}
Exemplo n.º 12
0
int_fast32_t pulse_get_source_info_list(pa_source_info_cb_t cb, void* userdata)
{
	if (pulse_context_ready() < 0)
		return -1;

	pulse_lock();

	pa_operation *op = pa_context_get_source_info_list(
		pulse_context, cb, userdata);
	while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
		pulse_wait();
	pa_operation_unref(op);

	pulse_unlock();

	return 0;
}
Exemplo n.º 13
0
void processContextState( pa_context* context, void* userData )
{
	StateData* stateData = static_cast<StateData*>( userData );
	pa_context_state_t state = ::pa_context_get_state( context );
	switch( state ) {
		case PA_CONTEXT_READY: {
			switch( stateData->request ) {
				case StateData::GET_SINKS:
					pa_operation_unref( pa_context_get_sink_info_list( context, processSinkInfo, userData ) );
				break;

				case StateData::GET_SOURCES:
					pa_operation_unref( pa_context_get_source_info_list( context, processSourceInfo, userData ) );
				break;

				case StateData::GET_DEFAULT_SINK_NAME:
					pa_operation_unref( pa_context_get_server_info( context, processServerInfo, userData ) );
				break;

				case StateData::GET_DEFAULT_SOURCE_NAME:
					pa_operation_unref( pa_context_get_server_info( context, processServerInfo, userData ) );
				break;

				case StateData::DONE:
					stateData->mainLoopApi->quit( stateData->mainLoopApi, 0 );
				break;

				case StateData::INVALID:
					stateData->mainLoopApi->quit( stateData->mainLoopApi, -1 );
				break;
			}
		}
		break;

		case PA_CONTEXT_TERMINATED:
			stateData->mainLoopApi->quit( stateData->mainLoopApi, 0 );
		break;

		case PA_CONTEXT_FAILED:
			stateData->mainLoopApi->quit( stateData->mainLoopApi, -1 );
		break;
		
		default:
		break;
	}
}
Exemplo n.º 14
0
const QStringList *get_source_names(){
    if(source_names == NULL){
        context_create();
        source_names = new QStringList();
        finished = false;

        pa_context_get_source_info_list(context, get_source_info_list_callback, NULL);

        do{
            pa_threaded_mainloop_lock(threaded_main_loop);
            pa_threaded_mainloop_wait(threaded_main_loop);
            qDebug("Received signal...");
        }while(! finished);
        pa_threaded_mainloop_unlock(threaded_main_loop);
        context_stop();
    }
    return source_names;
}
Exemplo n.º 15
0
void context_state_cb(pa_context *c, void *userdata) {

    switch (pa_context_get_state(c)) {
    case PA_CONTEXT_UNCONNECTED:
    case PA_CONTEXT_CONNECTING:
    case PA_CONTEXT_AUTHORIZING:
    case PA_CONTEXT_SETTING_NAME:
	break;

    case PA_CONTEXT_READY: {
    printf("func = %s , LINE = %d \n",__func__,__LINE__);
	pa_operation *o;

	// set up a callback to tell us about source devices
	if (!(o = pa_context_get_source_info_list(c,
					    sourcelist_cb,
					    NULL
						  ))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	// set up a callback to tell us about sink devices
	if (!(o = pa_context_get_sink_info_list(c,
					    sinklist_cb,
					    NULL
						  ))) {
	    show_error(_("pa_context_subscribe() failed"));
	    return;
	}
	pa_operation_unref(o);

	break;
    }

    case PA_CONTEXT_FAILED:
    case PA_CONTEXT_TERMINATED:
    default:
	return;
    }
}
JNIEXPORT jlong JNICALL
Java_org_jitsi_impl_neomedia_pulseaudio_PA_context_1get_1source_1info_1list
    (JNIEnv *env, jclass clazz, jlong c, jobject cb)
{
    jweak weakCb = cb ? (*env)->NewWeakGlobalRef(env, cb) : NULL;
    pa_operation *o;

    if ((*env)->ExceptionCheck(env))
        o = NULL;
    else
    {
        o
            = pa_context_get_source_info_list(
                    (pa_context *) (intptr_t) c,
                    weakCb ? PulseAudio_sourceInfoCallback : NULL,
                    (void *) weakCb);
    }

    return (intptr_t) o;
}
Exemplo n.º 17
0
static void probe_devices(ALboolean capture)
{
    pa_threaded_mainloop *loop;

    if(capture == AL_FALSE)
        allDevNameMap = malloc(sizeof(DevMap) * 1);
    else
        allCaptureDevNameMap = malloc(sizeof(DevMap) * 1);

    if((loop=pa_threaded_mainloop_new()) &&
       pa_threaded_mainloop_start(loop) >= 0)
    {
        pa_context *context;

        pa_threaded_mainloop_lock(loop);
        context = connect_context(loop, AL_FALSE);
        if(context)
        {
            pa_operation *o;

            if(capture == AL_FALSE)
                o = pa_context_get_sink_info_list(context, sink_device_callback, loop);
            else
                o = pa_context_get_source_info_list(context, source_device_callback, loop);
            while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
                pa_threaded_mainloop_wait(loop);
            pa_operation_unref(o);

            pa_context_disconnect(context);
            pa_context_unref(context);
        }
        pa_threaded_mainloop_unlock(loop);
        pa_threaded_mainloop_stop(loop);
    }
    if(loop)
        pa_threaded_mainloop_free(loop);
}
Exemplo n.º 18
0
// call this while holding the main loop lock
static int refresh_devices(struct SoundIoPrivate *si) {
    struct SoundIo *soundio = &si->pub;
    struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;

    assert(!sipa->current_devices_info);
    sipa->current_devices_info = ALLOCATE(struct SoundIoDevicesInfo, 1);
    if (!sipa->current_devices_info)
        return SoundIoErrorNoMem;

    pa_operation *list_sink_op = pa_context_get_sink_info_list(sipa->pulse_context, sink_info_callback, si);
    pa_operation *list_source_op = pa_context_get_source_info_list(sipa->pulse_context, source_info_callback, si);
    pa_operation *server_info_op = pa_context_get_server_info(sipa->pulse_context, server_info_callback, si);

    int err;
    if ((err = perform_operation(si, list_sink_op))) {
        return err;
    }
    if ((err = perform_operation(si, list_source_op))) {
        return err;
    }
    if ((err = perform_operation(si, server_info_op))) {
        return err;
    }

    if (sipa->device_query_err) {
        return sipa->device_query_err;
    }

    // based on the default sink name, figure out the default output index
    // if the name doesn't match just pick the first one. if there are no
    // devices then we need to set it to -1.
    sipa->current_devices_info->default_output_index = -1;
    sipa->current_devices_info->default_input_index = -1;

    if (sipa->current_devices_info->input_devices.length > 0) {
        sipa->current_devices_info->default_input_index = 0;
        for (int i = 0; i < sipa->current_devices_info->input_devices.length; i += 1) {
            struct SoundIoDevice *device = SoundIoListDevicePtr_val_at(
                    &sipa->current_devices_info->input_devices, i);

            assert(device->aim == SoundIoDeviceAimInput);
            if (strcmp(device->id, sipa->default_source_name) == 0) {
                sipa->current_devices_info->default_input_index = i;
            }
        }
    }

    if (sipa->current_devices_info->output_devices.length > 0) {
        sipa->current_devices_info->default_output_index = 0;
        for (int i = 0; i < sipa->current_devices_info->output_devices.length; i += 1) {
            struct SoundIoDevice *device = SoundIoListDevicePtr_val_at(
                    &sipa->current_devices_info->output_devices, i);

            assert(device->aim == SoundIoDeviceAimOutput);
            if (strcmp(device->id, sipa->default_sink_name) == 0) {
                sipa->current_devices_info->default_output_index = i;
            }
        }
    }

    soundio_destroy_devices_info(sipa->ready_devices_info);
    sipa->ready_devices_info = sipa->current_devices_info;
    sipa->current_devices_info = NULL;
    pa_threaded_mainloop_signal(sipa->main_loop, 0);
    soundio->on_events_signal(soundio);

    return 0;
}
Exemplo n.º 19
0
PyObject * quisk_pa_sound_devices(PyObject * self, PyObject * args)
{	// Return a list of PulseAudio device names [pycapt, pyplay]
	PyObject * pylist, * pycapt, * pyplay;
	pa_mainloop *pa_names_ml;
	pa_mainloop_api *pa_names_mlapi;
	pa_operation *pa_op=NULL;
	pa_context *pa_names_ctx;
	int state = 0;

	if (!PyArg_ParseTuple (args, ""))
		return NULL;
	// Each pycapt and pyplay is (dev name, description, alsa name)
	pylist = PyList_New(0);		// list [pycapt, pyplay]
	pycapt = PyList_New(0);		// list of capture devices
	pyplay = PyList_New(0);		// list of play devices
	PyList_Append(pylist, pycapt);
	PyList_Append(pylist, pyplay);
    
    //printf("Starting name loop\n");

	// Create a mainloop API and connection to the default server
	pa_names_ml = pa_mainloop_new();
	pa_names_mlapi = pa_mainloop_get_api(pa_names_ml);
	pa_names_ctx = pa_context_new(pa_names_mlapi, "DeviceNames");
 
	// This function connects to the pulse server
	if (pa_context_connect(pa_names_ctx, NULL, 0, NULL) < 0) {
	   if (quisk_sound_state.verbose_pulse)
	      printf("No local daemon to connect to for show_pulse_audio_devices option\n");
	   return pylist;
	}

	// This function defines a callback so the server will tell us it's state.
	pa_context_set_state_callback(pa_names_ctx, pa_names_state_cb, &state);

	// Now we'll enter into an infinite loop until we get the data we receive or if there's an error
	while (state < 10) {
		switch (state) {
		case 0:	// We can't do anything until PA is ready
			pa_mainloop_iterate(pa_names_ml, 1, NULL);
			break;
		case 1:
			// This sends an operation to the server.  pa_sinklist_info is
			// our callback function and a pointer to our devicelist will
			// be passed to the callback.
			pa_op = pa_context_get_sink_info_list(pa_names_ctx, pa_sinklist_cb, pyplay);
			// Update state for next iteration through the loop
			state++;
			pa_mainloop_iterate(pa_names_ml, 1, NULL);
			break;
		case 2:
			// Now we wait for our operation to complete.  When it's
			// complete our pa_output_devicelist is filled out, and we move
			// along to the next state
			if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
				pa_operation_unref(pa_op);
				// Now we perform another operation to get the source
				// (input device) list just like before.
				pa_op = pa_context_get_source_info_list(pa_names_ctx, pa_sourcelist_cb, pycapt);
				// Update the state so we know what to do next
				state++;
			}
			pa_mainloop_iterate(pa_names_ml, 1, NULL);
			break;
		case 3:
			if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
				pa_operation_unref(pa_op);
				state = 9;
			}
			else
				pa_mainloop_iterate(pa_names_ml, 1, NULL);
			break;
		case 9:				// Now we're done, clean up and disconnect and return
			pa_context_disconnect(pa_names_ctx);
			pa_context_unref(pa_names_ctx);
			pa_mainloop_free(pa_names_ml);
			state = 99;
			break;
		}
	}
    //printf("Finished with name loop\n");
	return pylist;
}
Exemplo n.º 20
0
void PulseSrc::make_device_description(pa_context* pulse_context) {
  if (!capture_devices_.empty()) capture_devices_.clear();
  pa_operation_unref(
      pa_context_get_source_info_list(pulse_context, get_source_info_callback, this));
}
Exemplo n.º 21
0
static void probe_devices(ALboolean capture)
{
    pa_threaded_mainloop *loop;

    if(capture == AL_FALSE)
        allDevNameMap = malloc(sizeof(DevMap) * 1);
    else
        allCaptureDevNameMap = malloc(sizeof(DevMap) * 1);

    if((loop=pa_threaded_mainloop_new()) &&
       pa_threaded_mainloop_start(loop) >= 0)
    {
        pa_context *context;

        pa_threaded_mainloop_lock(loop);
        context = connect_context(loop, AL_FALSE);
        if(context)
        {
            pa_operation *o;

            if(capture == AL_FALSE)
            {
                pa_stream_flags_t flags;
                pa_sample_spec spec;
                pa_stream *stream;

                flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
                        PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE;

                spec.format = PA_SAMPLE_S16NE;
                spec.rate = 44100;
                spec.channels = 2;

                stream = connect_playback_stream(NULL, loop, context, flags,
                                                 NULL, &spec, NULL);
                if(stream)
                {
                    o = pa_context_get_sink_info_by_name(context, pa_stream_get_device_name(stream), sink_device_callback, loop);
                    WAIT_FOR_OPERATION(o, loop);

                    pa_stream_disconnect(stream);
                    pa_stream_unref(stream);
                    stream = NULL;
                }

                o = pa_context_get_sink_info_list(context, sink_device_callback, loop);
            }
            else
            {
                pa_stream_flags_t flags;
                pa_sample_spec spec;
                pa_stream *stream;

                flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
                        PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE;

                spec.format = PA_SAMPLE_S16NE;
                spec.rate = 44100;
                spec.channels = 1;

                stream = connect_record_stream(NULL, loop, context, flags,
                                               NULL, &spec, NULL);
                if(stream)
                {
                    o = pa_context_get_source_info_by_name(context, pa_stream_get_device_name(stream), source_device_callback, loop);
                    WAIT_FOR_OPERATION(o, loop);

                    pa_stream_disconnect(stream);
                    pa_stream_unref(stream);
                    stream = NULL;
                }

                o = pa_context_get_source_info_list(context, source_device_callback, loop);
            }
            WAIT_FOR_OPERATION(o, loop);

            pa_context_disconnect(context);
            pa_context_unref(context);
        }
        pa_threaded_mainloop_unlock(loop);
        pa_threaded_mainloop_stop(loop);
    }
    if(loop)
        pa_threaded_mainloop_free(loop);
}
Exemplo n.º 22
0
AudioDevPulseAudio::AudioDevPulseAudio(QObject *parent):
    AudioDev(parent)
{
    this->d = new AudioDevPulseAudioPrivate(this);

    // Create a threaded main loop for PulseAudio
    this->d->m_mainLoop = pa_threaded_mainloop_new();

    if (!this->d->m_mainLoop)
        return;

    // Start main loop.
    if (pa_threaded_mainloop_start(this->d->m_mainLoop) != 0) {
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    pa_threaded_mainloop_lock(this->d->m_mainLoop);

    // Get main loop abstration layer.
    auto mainLoopApi = pa_threaded_mainloop_get_api(this->d->m_mainLoop);

    if (!mainLoopApi) {
        pa_threaded_mainloop_unlock(this->d->m_mainLoop);
        pa_threaded_mainloop_stop(this->d->m_mainLoop);
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    // Get a PulseAudio context.
    this->d->m_context = pa_context_new(mainLoopApi,
                                        QCoreApplication::applicationName()
                                           .toStdString()
                                           .c_str());

    if (!this->d->m_context) {
        pa_threaded_mainloop_unlock(this->d->m_mainLoop);
        pa_threaded_mainloop_stop(this->d->m_mainLoop);
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    // We need to set a state callback in order to connect to the server.
    pa_context_set_state_callback(this->d->m_context,
                                  AudioDevPulseAudioPrivate::contextStateCallbackInit,
                                  this);

    // Connect to PulseAudio server.
    if (pa_context_connect(this->d->m_context,
                           nullptr,
                           PA_CONTEXT_NOFLAGS,
                           nullptr) < 0) {
        pa_context_unref(this->d->m_context);
        this->d->m_context = nullptr;
        pa_threaded_mainloop_unlock(this->d->m_mainLoop);
        pa_threaded_mainloop_stop(this->d->m_mainLoop);
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    static const QList<pa_context_state_t> expectedStates = {
        PA_CONTEXT_READY,
        PA_CONTEXT_FAILED,
        PA_CONTEXT_TERMINATED
    };

    pa_context_state_t state;

    // Wait until the connection to the server is stablished.
    forever {
        state = pa_context_get_state(this->d->m_context);

        if (expectedStates.contains(state))
            break;

        pa_threaded_mainloop_wait(this->d->m_mainLoop);
    }

    if (state != PA_CONTEXT_READY) {
        pa_context_disconnect(this->d->m_context);
        pa_context_unref(this->d->m_context);
        this->d->m_context = nullptr;
        pa_threaded_mainloop_unlock(this->d->m_mainLoop);
        pa_threaded_mainloop_stop(this->d->m_mainLoop);
        pa_threaded_mainloop_free(this->d->m_mainLoop);
        this->d->m_mainLoop = nullptr;

        return;
    }

    // Get server information.
    auto operation =
            pa_context_get_server_info(this->d->m_context,
                                       AudioDevPulseAudioPrivate::serverInfoCallback,
                                       this);

    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(this->d->m_mainLoop);

    pa_operation_unref(operation);

    // Get sources information.
    operation = pa_context_get_source_info_list(this->d->m_context,
                                                AudioDevPulseAudioPrivate::sourceInfoCallback,
                                                this);

    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(this->d->m_mainLoop);

    pa_operation_unref(operation);

    // Get sinks information.
    operation = pa_context_get_sink_info_list(this->d->m_context,
                                              AudioDevPulseAudioPrivate::sinkInfoCallback,
                                              this);

    while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
        pa_threaded_mainloop_wait(this->d->m_mainLoop);

    pa_operation_unref(operation);

    pa_context_set_subscribe_callback(this->d->m_context,
                                      AudioDevPulseAudioPrivate::deviceUpdateCallback,
                                      this);

    pa_operation_unref(pa_context_subscribe(this->d->m_context,
                                            pa_subscription_mask_t(PA_SUBSCRIPTION_MASK_SINK
                                                                   | PA_SUBSCRIPTION_MASK_SOURCE
                                                                   | PA_SUBSCRIPTION_MASK_SERVER),
                                            nullptr,
                                            this));

    pa_threaded_mainloop_unlock(this->d->m_mainLoop);
}
Exemplo n.º 23
0
static void context_state_callback(pa_context *c, void *userdata) {
    if ( pa_context_get_state(c) == PA_CONTEXT_READY )
    {
        pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, userdata));
    }
}
Exemplo n.º 24
0
/*
 * iterate the main loop until all devices are listed
 * args:
 *    audio_ctx - pointer to audio context
 *
 * asserts:
 *    audio_ctx is not null
 *
 * returns: error code
 */
static int pa_get_devicelist(audio_context_t *audio_ctx)
{
	/*assertions*/
	assert(audio_ctx != NULL);

	/* Define our pulse audio loop and connection variables */
	pa_mainloop *pa_ml;
	pa_mainloop_api *pa_mlapi;
	pa_operation *pa_op = NULL;
	pa_context *pa_ctx;

	/* We'll need these state variables to keep track of our requests */
    int state = 0;
    int pa_ready = 0;

    /* Create a mainloop API and connection to the default server */
    pa_ml = pa_mainloop_new();
    pa_mlapi = pa_mainloop_get_api(pa_ml);
    pa_ctx = pa_context_new(pa_mlapi, "getDevices");

    /* This function connects to the pulse server */
    if(pa_context_connect(pa_ctx, NULL, 0, NULL) < 0)
    {
		fprintf(stderr,"AUDIO: PULSE - unable to connect to server: pa_context_connect failed\n");
		finish(pa_ctx, pa_ml);
		return -1;
	}

    /*
	 * This function defines a callback so the server will tell us
	 * it's state.
     * Our callback will wait for the state to be ready.
     * The callback will modify the variable to 1 so we know when we
     * have a connection and it's ready.
     * If there's an error, the callback will set pa_ready to 2
	 */
    pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready);

    /*
	 * Now we'll enter into an infinite loop until we get the data
	 * we receive or if there's an error
	 */
    for (;;)
	{
        /*
		 * We can't do anything until PA is ready,
		 * so just iterate the mainloop and continue
		 */
        if (pa_ready == 0)
		{
            pa_mainloop_iterate(pa_ml, 1, NULL);
            continue;
        }
        /* We couldn't get a connection to the server, so exit out */
        if (pa_ready == 2)
		{
            finish(pa_ctx, pa_ml);
            return -1;
        }
        /*
		 * At this point, we're connected to the server and ready
		 * to make requests
		 */
        switch (state)
		{
            /* State 0: we haven't done anything yet */
            case 0:
                /*
				 * This sends an operation to the server.
				 * pa_sinklist_cb is our callback function and a pointer
				 * o our devicelist will be passed to the callback
				 * (audio_ctx) The operation ID is stored in the
                 * pa_op variable
				 */
                pa_op = pa_context_get_sink_info_list(
						  pa_ctx,
                          pa_sinklist_cb,
                          (void *) audio_ctx);

                /* Update state for next iteration through the loop */
                state++;
                break;
            case 1:
                /*
				 * Now we wait for our operation to complete.
				 * When it's complete our pa_output_devicelist is
				 * filled out, and we move along to the next state
				 */
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE)
				{
                    pa_operation_unref(pa_op);

                    /*
					 * Now we perform another operation to get the
					 * source(input device) list just like before.
					 * This time we pass a pointer to our input structure
					 */
                    pa_op = pa_context_get_source_info_list(
							  pa_ctx,
                              pa_sourcelist_cb,
                              (void *) audio_ctx);
                    /* Update the state so we know what to do next */
                    state++;
                }
                break;
            case 2:
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE)
				{
                    /*
                     * Now we're done,
                     * clean up and disconnect and return
                     */
                    pa_operation_unref(pa_op);
                    finish(pa_ctx, pa_ml);
                    return 0;
                }
                break;
            default:
                /* We should never see this state */
                printf("AUDIO: Pulseaudio in state %d\n", state);
                return -1;
        }
        /*
		 * Iterate the main loop and go again.  The second argument is whether
         * or not the iteration should block until something is ready to be
         * done.  Set it to zero for non-blocking.
		 */
        pa_mainloop_iterate(pa_ml, 1, NULL);
    }

    return 0;
}
PulseAudioWrapper::PulseAudioWrapper(QObject *parent)
    : QObject(parent),
      d(new PulseAudioWrapperPrivate(this))
{
    PulseAudioWrapperPrivate::paMainLoop = pa_threaded_mainloop_new();
    pa_threaded_mainloop_start(PulseAudioWrapperPrivate::paMainLoop);

    PulseAudioWrapperPrivate::paMainLoopApi = pa_threaded_mainloop_get_api(PulseAudioWrapperPrivate::paMainLoop);

    pa_threaded_mainloop_lock(PulseAudioWrapperPrivate::paMainLoop);

    PulseAudioWrapperPrivate::paContext = pa_context_new(PulseAudioWrapperPrivate::paMainLoopApi,
                                                         qApp->applicationName().toUtf8().data());

    pa_context_set_state_callback(PulseAudioWrapperPrivate::paContext, &PulseAudioWrapperPrivate::onContextNotify, NULL);
    pa_context_connect(PulseAudioWrapperPrivate::paContext, NULL, PA_CONTEXT_NOFLAGS, NULL);

    bool done = false;
    pa_context_state_t contextState;

    while (!done)
    {
        switch (contextState = pa_context_get_state(d->paContext))
        {
            case PA_CONTEXT_UNCONNECTED: qDebug() << "Context state: PA_CONTEXT_UNCONNECTED"; break;
            case PA_CONTEXT_CONNECTING: qDebug() << "Context state: PA_CONTEXT_CONNECTING"; break;
            case PA_CONTEXT_AUTHORIZING: qDebug() << "Context state: PA_CONTEXT_AUTHORIZING"; break;
            case PA_CONTEXT_SETTING_NAME: qDebug() << "Context state: PA_CONTEXT_SETTING_NAME"; break;
            case PA_CONTEXT_READY: qDebug() << "Context state: PA_CONTEXT_READY"; done = true; break;
            case PA_CONTEXT_FAILED: qDebug() << "Context state: PA_CONTEXT_FAILED"; done = true; break;
            case PA_CONTEXT_TERMINATED: qDebug() << "Context state: PA_CONTEXT_TERMINATED"; done = true; break;
        }

        if (!done)
            pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    }

    if (contextState != PA_CONTEXT_READY)
        throw CallRecorderException("Unable to connect PulseAudio context!");

    pa_operation* listCardsOp = pa_context_get_card_info_list(PulseAudioWrapperPrivate::paContext,
                                                         &PulseAudioWrapperPrivate::onCardInfoList,
                                                         d.data());
    pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    pa_operation_unref(listCardsOp);

    pa_operation* listSinksOp = pa_context_get_sink_info_list(PulseAudioWrapperPrivate::paContext,
                                                             &PulseAudioWrapperPrivate::onSinkInfoList,
                                                             d.data());
    pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    pa_operation_unref(listSinksOp);

    pa_operation* listSourcesOp = pa_context_get_source_info_list(PulseAudioWrapperPrivate::paContext,
                                                                  &PulseAudioWrapperPrivate::onSourceInfoList,
                                                                  d.data());
    pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    pa_operation_unref(listSourcesOp);

    pa_context_set_subscribe_callback(PulseAudioWrapperPrivate::paContext,
                                      &PulseAudioWrapperPrivate::onContextSubscription,
                                      d.data());

    pa_operation* subscriptionOp = pa_context_subscribe(PulseAudioWrapperPrivate::paContext,
                                                        static_cast< pa_subscription_mask_t >(
                                                            PA_SUBSCRIPTION_MASK_CARD |
                                                            PA_SUBSCRIPTION_MASK_SINK |
                                                            PA_SUBSCRIPTION_MASK_SOURCE),
                                                        &PulseAudioWrapperPrivate::onContextSubscriptionSuccess,
                                                        d.data());
    pa_threaded_mainloop_wait(PulseAudioWrapperPrivate::paMainLoop);
    pa_operation_unref(subscriptionOp);


    pa_threaded_mainloop_unlock(PulseAudioWrapperPrivate::paMainLoop);
}
int pa_get_devicelist(pa_devicelist_t *input, pa_devicelist_t *output) {
    // Define our pulse audio loop and connection variables
    pa_mainloop *pa_ml;
    pa_mainloop_api *pa_mlapi;
    pa_operation *pa_op;
    pa_context *pa_ctx;

    // We'll need these state variables to keep track of our requests
    int state = 0;
    int pa_ready = 0;

    // Initialize our device lists
    memset(input, 0, sizeof(pa_devicelist_t) * 16);
    memset(output, 0, sizeof(pa_devicelist_t) * 16);

    // Create a mainloop API and connection to the default server
    pa_ml = pa_mainloop_new();
    pa_mlapi = pa_mainloop_get_api(pa_ml);
    pa_ctx = pa_context_new(pa_mlapi, "test");

    // This function connects to the pulse server
    pa_context_connect(pa_ctx, NULL, 0, NULL);

    // This function defines a callback so the server will tell us it's state.
    // Our callback will wait for the state to be ready.  The callback will
    // modify the variable to 1 so we know when we have a connection and it's
    // ready.
    // If there's an error, the callback will set pa_ready to 2
    pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready);

    // Now we'll enter into an infinite loop until we get the data we receive
    // or if there's an error
    for (;;) {
        // We can't do anything until PA is ready, so just iterate the mainloop
        // and continue
        if (pa_ready == 0) {
            pa_mainloop_iterate(pa_ml, 1, NULL);
            continue;
        }
        // We couldn't get a connection to the server, so exit out
        if (pa_ready == 2) {
            pa_context_disconnect(pa_ctx);
            pa_context_unref(pa_ctx);
            pa_mainloop_free(pa_ml);
            return -1;
        }
        // At this point, we're connected to the server and ready to make
        // requests
        switch (state) {
            // State 0: we haven't done anything yet
            case 0:
                // This sends an operation to the server.  pa_sinklist_info is
                // our callback function and a pointer to our devicelist will
                // be passed to the callback The operation ID is stored in the
                // pa_op variable
                pa_op = pa_context_get_sink_info_list(pa_ctx,
                        pa_sinklist_cb,
                        output
                        );

                // Update state for next iteration through the loop
                state++;
                break;
            
            case 1:
                // Now we wait for our operation to complete.  When it's
                // complete our pa_output_devicelist is filled out, and we move
                // along to the next state
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
                    pa_operation_unref(pa_op);

                    // Now we perform another operation to get the source
                    // (input device) list just like before.  This time we pass
                    // a pointer to our input structure
                    pa_op = pa_context_get_source_info_list(pa_ctx,
                            pa_sourcelist_cb,
                            input
                            );
                    // Update the state so we know what to do next
                    state++;
                }
                break;
            case 2:
                if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
                    // Now we're done, clean up and disconnect and return
                    pa_operation_unref(pa_op);
                    pa_context_disconnect(pa_ctx);
                    pa_context_unref(pa_ctx);
                    pa_mainloop_free(pa_ml);
                    return 0;
                }
                break;
            default:
                // We should never see this state
                fprintf(stderr, "in state %d\n", state);
                return -1;
        }
        // Iterate the main loop and go again.  The second argument is whether
        // or not the iteration should block until something is ready to be
        // done.  Set it to zero for non-blocking.
        pa_mainloop_iterate(pa_ml, 1, NULL);
    }
}
Exemplo n.º 27
0
void Context::contextStateCallback(pa_context *c)
{
    qCDebug(PLASMAPA) << "state callback";
    pa_context_state_t state = pa_context_get_state(c);
    if (state == PA_CONTEXT_READY) {
        qCDebug(PLASMAPA) << "ready";

        // 1. Register for the stream changes (except during probe)
        if (m_context == c) {
            pa_context_set_subscribe_callback(c, subscribe_cb, this);

            if (!PAOperation(pa_context_subscribe(c, (pa_subscription_mask_t)
                                           (PA_SUBSCRIPTION_MASK_SINK|
                                            PA_SUBSCRIPTION_MASK_SOURCE|
                                            PA_SUBSCRIPTION_MASK_CLIENT|
                                            PA_SUBSCRIPTION_MASK_SINK_INPUT|
                                            PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT|
                                            PA_SUBSCRIPTION_MASK_CARD|
                                            PA_SUBSCRIPTION_MASK_SERVER), nullptr, nullptr))) {
                qCWarning(PLASMAPA) << "pa_context_subscribe() failed";
                return;
            }
        }

        if (!PAOperation(pa_context_get_sink_info_list(c, sink_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_sink_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_source_info_list(c, source_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_source_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_client_info_list(c, client_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_client_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_card_info_list(c, card_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_card_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_sink_input_info_list(c, sink_input_callback, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_sink_input_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_source_output_info_list(c, source_output_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_source_output_info_list() failed";
            return;
        }

        if (!PAOperation(pa_context_get_server_info(c, server_cb, this))) {
            qCWarning(PLASMAPA) << "pa_context_get_server_info() failed";
            return;
        }

        if (PAOperation(pa_ext_stream_restore_read(c, ext_stream_restore_read_cb, this))) {
            pa_ext_stream_restore_set_subscribe_cb(c, ext_stream_restore_subscribe_cb, this);
            PAOperation(pa_ext_stream_restore_subscribe(c, 1, nullptr, this));
        } else {
            qCWarning(PLASMAPA) << "Failed to initialize stream_restore extension";
        }
    } else if (!PA_CONTEXT_IS_GOOD(state)) {
        qCWarning(PLASMAPA) << "context kaput";
        if (m_context) {
            pa_context_unref(m_context);
            m_context = nullptr;
        }
        reset();
        QTimer::singleShot(1000, this, &Context::connectToDaemon);
    }
}
Exemplo n.º 28
0
static void cm_sink_port_set_cb(pa_context *context, int success, void *user_data)
{
	pa_operation *op;
	op = pa_context_get_source_info_list(context, cm_sourceinfo_cb, user_data);
	pa_operation_unref(op);
}