diff --git a/src/modules/mixer/sys_pulse.c b/src/modules/mixer/sys_pulse.c index d55f675ac..badfdcf19 100644 --- a/src/modules/mixer/sys_pulse.c +++ b/src/modules/mixer/sys_pulse.c @@ -1,7 +1,6 @@ #include "e_mod_main.h" #include "Pulse.h" -//#define BAD_CH_MAPPING 1 #define PULSE_BUS "org.PulseAudio.Core1" #define PULSE_PATH "/org/pulseaudio/core1" @@ -16,12 +15,15 @@ static Ecore_Event_Handler *pdh = NULL; static Eina_List *sinks = NULL; static Eina_List *sources = NULL; static Ecore_Poller *pulse_poller = NULL; +static Eina_Hash *queue_states = NULL; static E_DBus_Connection *dbus = NULL; static E_DBus_Signal_Handler *dbus_handler = NULL; static Ecore_Timer *disc_timer = NULL; static unsigned int disc_count = 0; +static unsigned int update_count = 0; +static Ecore_Timer *update_timer = NULL; static Eina_Bool _pulse_poller_cb(void *d __UNUSED__) @@ -108,6 +110,14 @@ _pulse_info_get(Pulse *d __UNUSED__, int type __UNUSED__, Pulse_Server_Info *ev) e_mod_mixer_pulse_ready(EINA_TRUE); } +static Eina_Bool +_pulse_update_timer(void *d EINA_UNUSED) +{ + e_mod_mixer_pulse_update(); + update_timer = NULL; + return EINA_FALSE; +} + static Eina_Bool _pulse_update(Pulse *d __UNUSED__, int type __UNUSED__, Pulse_Sink *ev __UNUSED__) { @@ -116,7 +126,8 @@ _pulse_update(Pulse *d __UNUSED__, int type __UNUSED__, Pulse_Sink *ev __UNUSED_ id = pulse_server_info_get(conn); if (id) pulse_cb_set(conn, id, (Pulse_Cb)_pulse_info_get); - e_mod_mixer_pulse_update(); + if (update_timer) ecore_timer_reset(update_timer); + else update_timer = ecore_timer_add(0.2, _pulse_update_timer, NULL); return EINA_TRUE; } @@ -189,6 +200,8 @@ _pulse_connected(Pulse *d, int type __UNUSED__, Pulse *ev) e_mixer_default_setup(); return ECORE_CALLBACK_RENEW; } + if (!queue_states) + queue_states = eina_hash_stringshared_new(free); pulse_cb_set(conn, id, (Pulse_Cb)_pulse_sinks_get); id = pulse_sources_get(conn); if (id) @@ -226,8 +239,12 @@ _pulse_disconnected(Pulse *d, int type __UNUSED__, Pulse *ev) EINA_LIST_FREE(sources, sink) pulse_sink_free(sink); pulse_server_info_free(info); + if (queue_states) eina_hash_free(queue_states); + queue_states = NULL; info = NULL; default_sink = NULL; + if (update_timer) ecore_timer_del(update_timer); + update_timer = NULL; // printf("PULSEAUDIO: disconnected at %g\n", ecore_time_unix_get()); @@ -237,6 +254,29 @@ _pulse_disconnected(Pulse *d, int type __UNUSED__, Pulse *ev) return ECORE_CALLBACK_RENEW; } +static void +_pulse_state_queue(Pulse_Sink *sink, int left, int right, int mute) +{ + E_Mixer_Channel_State *state = NULL; + + if (queue_states) + state = eina_hash_find(queue_states, pulse_sink_name_get(sink)); + else + queue_states = eina_hash_stringshared_new(free); + if (!state) + { + state = E_NEW(E_Mixer_Channel_State, 1); + eina_hash_direct_add(queue_states, pulse_sink_name_get(sink), state); + state->left = state->right = state->mute = -1; + } + if (left >= 0) + state->left = left; + if (right >= 0) + state->right = right; + if (mute >= 0) + state->mute = mute; +} + static Pulse_Sink * _pulse_sink_find(const char *name) { @@ -261,10 +301,37 @@ _pulse_sink_find(const char *name) return NULL; } +static Eina_Bool +_pulse_queue_process(const Eina_Hash *h EINA_UNUSED, const char *key, E_Mixer_Channel_State *state, void *d EINA_UNUSED) +{ + Eina_List *l, *list[2] = {sinks, sources}; + void *s, *ch; + int x; + + if ((state->mute == -1) && (state->left == -1) && (state->right == -1)) return EINA_TRUE; + ch = (void*)1; + for (x = 0; x < 2; x++) + EINA_LIST_FOREACH(list[x], l, s) + { + if (key != pulse_sink_name_get(s)) continue; + if ((state->left >= 0) || (state->right >= 0)) + e_mixer_pulse_set_volume(s, &ch, state->left, state->right); + if (state->mute >= 0) + e_mixer_pulse_set_mute(s, &ch, state->mute); + state->left = state->right = state->mute = -1; + return EINA_FALSE; + } + return EINA_TRUE; +} + static void _pulse_result_cb(Pulse *p __UNUSED__, Pulse_Tag_Id id, void *ev) { if (!ev) fprintf(stderr, "Command %u failed!\n", id); + if (!update_count) return; + if (--update_count) return; + if (!queue_states) return; + eina_hash_foreach(queue_states, (Eina_Hash_Foreach)_pulse_queue_process, NULL); } Eina_Bool @@ -336,6 +403,9 @@ e_mixer_pulse_shutdown(void) pulse_server_info_free(info); info = NULL; default_sink = NULL; + update_count = 0; + if (update_timer) ecore_timer_del(update_timer); + update_timer = NULL; pulse_free(conn); conn = NULL; @@ -345,6 +415,8 @@ e_mixer_pulse_shutdown(void) pch = NULL; if (pdh) ecore_event_handler_del(pdh); pdh = NULL; + if (queue_states) eina_hash_free(queue_states); + queue_states = NULL; if (dbus_handler) { e_dbus_signal_handler_del(dbus, dbus_handler); @@ -410,19 +482,9 @@ e_mixer_pulse_get_card_name(const char *card) } Eina_List * -e_mixer_pulse_get_channels(E_Mixer_System *self) +e_mixer_pulse_get_channels(E_Mixer_System *self EINA_UNUSED) { - Eina_List *ret = NULL; - -#ifdef BAD_CH_MAPPING - uintptr_t id; - for (id = 0; id < pulse_sink_channels_count((void *)self); id++) - ret = eina_list_append(ret, (void *)(id + 1)); -#else - (void)self; - ret = eina_list_append(ret, (void *)(1)); -#endif - return ret; + return eina_list_append(NULL, (void *)(1)); } void @@ -432,14 +494,9 @@ e_mixer_pulse_free_channels(Eina_List *channels) } Eina_List * -e_mixer_pulse_get_channels_names(E_Mixer_System *self) +e_mixer_pulse_get_channels_names(E_Mixer_System *self EINA_UNUSED) { -#ifdef BAD_CH_MAPPING - return pulse_sink_channel_names_get((void *)self); -#else - (void)self; return eina_list_append(NULL, eina_stringshare_add("Output")); -#endif } void @@ -451,28 +508,15 @@ e_mixer_pulse_free_channels_names(Eina_List *channels_names) } const char * -e_mixer_pulse_get_default_channel_name(E_Mixer_System *self) +e_mixer_pulse_get_default_channel_name(E_Mixer_System *self EINA_UNUSED) { -#ifdef BAD_CH_MAPPING - return e_mixer_pulse_get_channel_name(self, 0); -#else - (void)self; return eina_stringshare_add("Output"); -#endif } E_Mixer_Channel * -e_mixer_pulse_get_channel_by_name(E_Mixer_System *self, const char *name) +e_mixer_pulse_get_channel_by_name(E_Mixer_System *self EINA_UNUSED, const char *name EINA_UNUSED) { -#ifdef BAD_CH_MAPPING - unsigned int x; - x = pulse_sink_channel_name_get_id((void *)self, name); - if (x == UINT_MAX) return NULL; - return (E_Mixer_Channel *)((uintptr_t)(x + 1)); -#else - (void)self, (void)name; return (E_Mixer_Channel *)1; -#endif } void @@ -481,30 +525,16 @@ e_mixer_pulse_channel_del(E_Mixer_Channel *channel __UNUSED__) } const char * -e_mixer_pulse_get_channel_name(E_Mixer_System *self, E_Mixer_Channel *channel) +e_mixer_pulse_get_channel_name(E_Mixer_System *self EINA_UNUSED, E_Mixer_Channel *channel) { if (!channel) return NULL; -#ifdef BAD_CH_MAPPING - return pulse_sink_channel_id_get_name((void *)self, - ((uintptr_t)channel) - 1); -#else - (void)self; return eina_stringshare_add("Output"); -#endif } int e_mixer_pulse_get_volume(E_Mixer_System *self, E_Mixer_Channel *channel, int *left, int *right) { double volume; - -#ifdef BAD_CH_MAPPING - if (!channel) return 0; - volume = pulse_sink_channel_volume_get((void *)self, - ((uintptr_t)channel) - 1); - if (left) *left = (int)volume; - if (right) *right = (int)volume; -#else int x, n; if (!channel) return 0; @@ -512,7 +542,7 @@ e_mixer_pulse_get_volume(E_Mixer_System *self, E_Mixer_Channel *channel, int *le for (x = 0; x < n; x++) { volume = pulse_sink_channel_volume_get((void *)self, - ((uintptr_t)channel) - 1); + ((uintptr_t)x)); if (x == 0) { if (left) *left = (int)volume; @@ -522,7 +552,6 @@ e_mixer_pulse_get_volume(E_Mixer_System *self, E_Mixer_Channel *channel, int *le if (right) *right = (int)volume; } } -#endif return 1; } @@ -530,20 +559,16 @@ int e_mixer_pulse_set_volume(E_Mixer_System *self, E_Mixer_Channel *channel, int left, int right) { uint32_t id = 0; - -#ifdef BAD_CH_MAPPING - if (!channel) return 0; - id = pulse_type_channel_volume_set(conn, (void *)self, - ((uintptr_t)channel) - 1, - (left + right) / 2, source); - if (!id) return 0; - pulse_cb_set(conn, id, (Pulse_Cb)_pulse_result_cb); -#else int x, n; if (!channel) return 0; + if (update_count > 1) + { + _pulse_state_queue((void*)self, left, right, -1); + return 1; + } n = pulse_sink_channels_count((void *)self); - for (x = 0; x < n; x++) + for (x = 0; x < n; x++, id = 0) { double vol; @@ -551,15 +576,19 @@ e_mixer_pulse_set_volume(E_Mixer_System *self, E_Mixer_Channel *channel, int lef if (x == 0) { if (vol != left) - id |= pulse_sink_channel_volume_set(conn, (void *)self, x, left); + id = pulse_sink_channel_volume_set(conn, (void *)self, x, left); } else if (x == 1) { if (vol != right) - id |= pulse_sink_channel_volume_set(conn, (void *)self, x, right); + id = pulse_sink_channel_volume_set(conn, (void *)self, x, right); + } + if (id) + { + pulse_cb_set(conn, id, (Pulse_Cb)_pulse_result_cb); + update_count++; } } -#endif return 1; } @@ -582,9 +611,15 @@ e_mixer_pulse_set_mute(E_Mixer_System *self, E_Mixer_Channel *channel __UNUSED__ uint32_t id; Eina_Bool source = EINA_FALSE; + if (update_count > 2) + { + _pulse_state_queue((void*)self, -1, -1, mute); + return 1; + } source = !!eina_list_data_find(sources, self); id = pulse_type_mute_set(conn, pulse_sink_idx_get((void *)self), mute, source); if (!id) return 0; + update_count++; pulse_cb_set(conn, id, (Pulse_Cb)_pulse_result_cb); return 1; } @@ -592,40 +627,18 @@ e_mixer_pulse_set_mute(E_Mixer_System *self, E_Mixer_Channel *channel __UNUSED__ int e_mixer_pulse_get_state(E_Mixer_System *self, E_Mixer_Channel *channel, E_Mixer_Channel_State *state) { -#ifdef BAD_CH_MAPPING - double vol; - if (!state) return 0; - if (!channel) return 0; - vol = pulse_sink_channel_volume_get((void *)self, - ((uintptr_t)channel) - 1); - state->mute = pulse_sink_muted_get((void *)self); - state->left = state->right = (int)vol; -#else if (!state) return 0; if (!channel) return 0; e_mixer_pulse_get_mute(self, channel, &(state->mute)); e_mixer_pulse_get_volume(self, channel, &(state->left), &(state->right)); -#endif return 1; } int e_mixer_pulse_set_state(E_Mixer_System *self, E_Mixer_Channel *channel, const E_Mixer_Channel_State *state) { -#ifdef BAD_CH_MAPPING - uint32_t id; - Eina_Bool source = EINA_FALSE; - if (!channel) return 0; - source = !!eina_list_data_find(sources, self); - id = pulse_type_channel_volume_set(conn, (void *)self, - ((uintptr_t)channel) - 1, - (state->left + state->right) / 2, source); - if (!id) return 0; - pulse_cb_set(conn, id, (Pulse_Cb)_pulse_result_cb); -#else e_mixer_pulse_set_volume(self, channel, state->left, state->right); e_mixer_pulse_set_mute(self, channel, state->mute); -#endif return 1; }