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; } }
static bool set_call_mode_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->in_call = luna_service_message_get_boolean(parsed_obj, "inCall", service->in_call); service->speaker_mode = luna_service_message_get_boolean(parsed_obj, "speakerMode", service->in_call); req = luna_service_req_data_new(handle, message); req->user_data = service; op = pa_context_get_card_info_list(service->context, cm_cardinfo_cb, req); pa_operation_unref(op); cleanup: if (!jis_null(parsed_obj)) j_release(&parsed_obj); return true; }
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); } }
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); }