-EXPORT_API
-int mm_sound_pa_flush(const int handle)
-{
- mm_sound_handle_t* phandle = NULL;
- int err = MM_ERROR_NONE;
-
- CHECK_HANDLE_RANGE(handle);
- GET_HANDLE_DATA(phandle, mm_sound_handle_mgr.handles, &handle, __mm_sound_handle_comparefunc);
- if(phandle == NULL)
- return MM_ERROR_SOUND_INTERNAL;
-
- if (0 > pa_simple_flush(phandle->s, &err)) {
- debug_error("pa_simple_flush() failed with %s\n", pa_strerror(err));
- err = MM_ERROR_SOUND_INTERNAL;
- }
-
- return err;
-}
-
-EXPORT_API
-int mm_sound_pa_get_latency(const int handle, int* latency)
-{
- mm_sound_handle_t* phandle = NULL;
- int err = MM_ERROR_NONE;
- pa_usec_t latency_time = 0;
-
- CHECK_HANDLE_RANGE(handle);
- GET_HANDLE_DATA(phandle, mm_sound_handle_mgr.handles, &handle, __mm_sound_handle_comparefunc);
- if(phandle == NULL) {
- debug_msg("phandle is null");
- return MM_ERROR_SOUND_INTERNAL;
- }
-
- latency_time = pa_simple_get_final_latency(phandle->s, &err);
- if (err > 0 && latency_time == 0) {
- debug_error("pa_simple_get_latency() failed with %s\n", pa_strerror(err));
- err = MM_ERROR_SOUND_INTERNAL;
- }
- *latency = latency_time / 1000; // usec to msec
-
- return err;
-}
-
-static void __mm_sound_pa_state_cb(pa_context *c, void *userdata)
-{
- pa_threaded_mainloop *mainloop = userdata;
-
- switch (pa_context_get_state(c)) {
- case PA_CONTEXT_READY:
- pa_threaded_mainloop_signal(mainloop, 0);
- break;
- case PA_CONTEXT_TERMINATED:
- case PA_CONTEXT_FAILED:
- pa_threaded_mainloop_signal(mainloop, 0);
- break;
-
- case PA_CONTEXT_UNCONNECTED:
- case PA_CONTEXT_CONNECTING:
- case PA_CONTEXT_AUTHORIZING:
- case PA_CONTEXT_SETTING_NAME:
- break;
- }
-}
-
-static void __mm_sound_pa_connect_to_pa()
-{
- if(mm_sound_handle_mgr.state)
- return;
-
- if (!(mm_sound_handle_mgr.mainloop = pa_threaded_mainloop_new())) {
- debug_error("mainloop create failed");
- }
-
- if (!(mm_sound_handle_mgr.context = pa_context_new(pa_threaded_mainloop_get_api(mm_sound_handle_mgr.mainloop), NULL))) {
- debug_error("context create failed");
- }
-
- pa_threaded_mainloop_lock(mm_sound_handle_mgr.mainloop);
- pa_context_set_state_callback(mm_sound_handle_mgr.context, __mm_sound_pa_state_cb, (void *)mm_sound_handle_mgr.mainloop);
-
- if(pa_threaded_mainloop_start(mm_sound_handle_mgr.mainloop) < 0) {
- debug_error("mainloop start failed");
- }
-
- if (pa_context_connect(mm_sound_handle_mgr.context, NULL, 0, NULL) < 0) {
- debug_error("context connect failed");
- }
-
- while (TRUE) {
- pa_context_state_t state = pa_context_get_state(mm_sound_handle_mgr.context);
-
- if (!PA_CONTEXT_IS_GOOD (state)) {
- break;
- }
-
- if (state == PA_CONTEXT_READY) {
- break;
- }
-
- debug_msg("waiting..................");
- pa_threaded_mainloop_wait(mm_sound_handle_mgr.mainloop);
- debug_msg("waiting DONE. check again...");
- }
-
- mm_sound_handle_mgr.state = TRUE;
-
- pa_threaded_mainloop_unlock(mm_sound_handle_mgr.mainloop);
-
-}
-
-static void __mm_sound_pa_success_cb(pa_context *c, int success, void *userdata)
-{
- pa_threaded_mainloop *mainloop = (pa_threaded_mainloop *)userdata;
-
- if (!success) {
- debug_error("pa control failed: %s\n", pa_strerror(pa_context_errno(c)));
- } else {
- debug_msg("pa control success\n");
- }
- pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-EXPORT_API
-int mm_sound_pa_set_call_mute(const int type, const int mute, int direction)
-{
- pa_operation *o = NULL;
-
- CHECK_VOLUME_TYPE_RANGE(type);
- CHECK_CONNECT_TO_PULSEAUDIO();
-
- pa_threaded_mainloop_lock(mm_sound_handle_mgr.mainloop);
-
- o = pa_ext_policy_set_mute(mm_sound_handle_mgr.context, -1, type, direction, mute, __mm_sound_pa_success_cb, (void *)mm_sound_handle_mgr.mainloop);
- WAIT_PULSEAUDIO_OPERATION(mm_sound_handle_mgr, o);
-
- if(o)
- pa_operation_unref(o);
-
- pa_threaded_mainloop_unlock(mm_sound_handle_mgr.mainloop);
-
- return MM_ERROR_NONE;
-}
-
-typedef struct _get_volume_max_userdata_t
-{
- pa_threaded_mainloop* mainloop;
- int value;
-} get_volume_max_userdata_t;
-
-static void __mm_sound_pa_get_cb(pa_context *c, uint32_t value, void *userdata)
-{
- get_volume_max_userdata_t* u = (get_volume_max_userdata_t*)userdata;
-
- assert(c);
- assert(u);
-
- u->value = value;
-
- pa_threaded_mainloop_signal(u->mainloop, 0);
-}
-
-
-EXPORT_API
-int mm_sound_pa_get_volume_level(int handle, const int type, int* level)
-{
- mm_sound_handle_t* phandle = NULL;
- get_volume_max_userdata_t userdata;
- pa_operation *o = NULL;
-
- CHECK_HANDLE_RANGE(handle);
- CHECK_VOLUME_TYPE_RANGE(type);
- CHECK_CONNECT_TO_PULSEAUDIO();
-
- GET_HANDLE_DATA(phandle, mm_sound_handle_mgr.handles, &handle, __mm_sound_handle_comparefunc);
- if(phandle == NULL) {
- debug_msg("phandle is null");
- return MM_ERROR_SOUND_INTERNAL;
- }
-
- pa_threaded_mainloop_lock(mm_sound_handle_mgr.mainloop);
-
- userdata.mainloop = mm_sound_handle_mgr.mainloop;
- userdata.value = -1;
-
- o = pa_ext_policy_get_volume_level(mm_sound_handle_mgr.context, phandle->stream_idx, type, __mm_sound_pa_get_cb, (void *)&userdata);
- WAIT_PULSEAUDIO_OPERATION(mm_sound_handle_mgr, o);
-
- if(userdata.value < 0) {
- debug_error("pa_ext_policy_get_volume_level() failed");
- *level = -1;
- pa_threaded_mainloop_unlock(mm_sound_handle_mgr.mainloop);
- return MM_ERROR_SOUND_INTERNAL;
- } else
- pa_operation_unref(o);
-
-
- *level = userdata.value;
-
- pa_threaded_mainloop_unlock(mm_sound_handle_mgr.mainloop);
-
- return MM_ERROR_NONE;
-}
-
-EXPORT_API
-int mm_sound_pa_set_volume_level(int handle, const int type, int level)
-{
- mm_sound_handle_t* phandle = NULL;
- pa_operation *o = NULL;
-
- CHECK_HANDLE_RANGE(handle);
- CHECK_VOLUME_TYPE_RANGE(type);
- CHECK_CONNECT_TO_PULSEAUDIO();
-
- GET_HANDLE_DATA(phandle, mm_sound_handle_mgr.handles, &handle, __mm_sound_handle_comparefunc);
- if(phandle == NULL) {
- debug_msg("phandle is null");
- return MM_ERROR_SOUND_INTERNAL;
- }
-
- pa_threaded_mainloop_lock(mm_sound_handle_mgr.mainloop);
-
- o = pa_ext_policy_set_volume_level(mm_sound_handle_mgr.context, phandle->stream_idx, type, level, __mm_sound_pa_success_cb, (void *)mm_sound_handle_mgr.mainloop);
- WAIT_PULSEAUDIO_OPERATION(mm_sound_handle_mgr, o);
-
- if(o)
- pa_operation_unref(o);
-
- pa_threaded_mainloop_unlock(mm_sound_handle_mgr.mainloop);
-
- return MM_ERROR_NONE;
-}
-
-EXPORT_API
-int mm_sound_pa_get_mute(int handle, const int type, int direction, int* mute)
-{
- mm_sound_handle_t* phandle = NULL;
- get_volume_max_userdata_t userdata;
- pa_operation *o = NULL;
-
- CHECK_HANDLE_RANGE(handle);
- CHECK_VOLUME_TYPE_RANGE(type);
- CHECK_CONNECT_TO_PULSEAUDIO();
-
- GET_HANDLE_DATA(phandle, mm_sound_handle_mgr.handles, &handle, __mm_sound_handle_comparefunc);
- if(phandle == NULL) {
- debug_msg("phandle is null");
- return MM_ERROR_SOUND_INTERNAL;
- }
-
- pa_threaded_mainloop_lock(mm_sound_handle_mgr.mainloop);
-
- userdata.mainloop = mm_sound_handle_mgr.mainloop;
- userdata.value = -1;
-
- o = pa_ext_policy_get_mute(mm_sound_handle_mgr.context, phandle->stream_idx, type, direction, __mm_sound_pa_get_cb, (void *)&userdata);
- WAIT_PULSEAUDIO_OPERATION(mm_sound_handle_mgr, o);
-
- if(userdata.value < 0) {
- debug_error("mm_sound_pa_get_mute() failed");
- *mute = -1;
- pa_threaded_mainloop_unlock(mm_sound_handle_mgr.mainloop);
- return MM_ERROR_SOUND_INTERNAL;
- } else
- pa_operation_unref(o);
-
- pa_threaded_mainloop_unlock(mm_sound_handle_mgr.mainloop);
-
- return MM_ERROR_NONE;
-}
-
-EXPORT_API
-int mm_sound_pa_set_mute(int handle, const int type, int direction, int mute)
-{
- mm_sound_handle_t* phandle = NULL;
- pa_operation *o = NULL;
-
- CHECK_HANDLE_RANGE(handle);
- CHECK_VOLUME_TYPE_RANGE(type);
- CHECK_CONNECT_TO_PULSEAUDIO();
-
- GET_HANDLE_DATA(phandle, mm_sound_handle_mgr.handles, &handle, __mm_sound_handle_comparefunc);
- if(phandle == NULL) {
- debug_msg("phandle is null");
- return MM_ERROR_SOUND_INTERNAL;
- }
-
- pa_threaded_mainloop_lock(mm_sound_handle_mgr.mainloop);
-
- o = pa_ext_policy_set_mute(mm_sound_handle_mgr.context, phandle->stream_idx, type, direction, mute, __mm_sound_pa_success_cb, (void *)mm_sound_handle_mgr.mainloop);
- WAIT_PULSEAUDIO_OPERATION(mm_sound_handle_mgr, o);
-
- if(o)
- pa_operation_unref(o);
-
- pa_threaded_mainloop_unlock(mm_sound_handle_mgr.mainloop);
-
- return MM_ERROR_NONE;
-}
-
-EXPORT_API
-int mm_sound_pa_corkall(int cork)
-{
- pa_operation *o = NULL;
-
- CHECK_CONNECT_TO_PULSEAUDIO();
-
- pa_threaded_mainloop_lock(mm_sound_handle_mgr.mainloop);
-
- o = pa_context_set_cork_all(mm_sound_handle_mgr.context, cork, __mm_sound_pa_success_cb, (void *)mm_sound_handle_mgr.mainloop);
- WAIT_PULSEAUDIO_OPERATION(mm_sound_handle_mgr, o);
-
- if(o)
- pa_operation_unref(o);
-
- pa_threaded_mainloop_unlock(mm_sound_handle_mgr.mainloop);
-
- return MM_ERROR_NONE;
-}
-