From eae3cd37e830b82fee160dbc67ea3a75971dffc7 Mon Sep 17 00:00:00 2001 From: "Michael Bouchaud (yoz)" Date: Thu, 14 May 2020 11:13:31 +0100 Subject: [PATCH] e_client_volume: Reparent sink if a new window comes and match this one Summary: This commit avoid multiple windows got the same sink. Like launching rage from terminology, gstreamer sink could be associated with terminology and rage window too. Reviewers: raster, devilhorns Subscribers: cedric, zmike Tags: #enlightenment-git Differential Revision: https://phab.enlightenment.org/D8929 --- src/modules/mixer/gadget/backend.c | 141 ++++++++++++++++------------- 1 file changed, 80 insertions(+), 61 deletions(-) diff --git a/src/modules/mixer/gadget/backend.c b/src/modules/mixer/gadget/backend.c index 66ebb2652..3afc0c187 100644 --- a/src/modules/mixer/gadget/backend.c +++ b/src/modules/mixer/gadget/backend.c @@ -45,6 +45,7 @@ static int _sink_input_min_get(void *data); static int _sink_input_max_get(void *data); static const char *_sink_input_name_get(void *data); static pid_t _get_ppid(pid_t pid); +static E_Client_Volume_Sink *_sink_input_e_client_volume_sink_find(Emix_Sink_Input *input, pid_t *ret_pid); static void _sink_input_event(int type, Emix_Sink_Input *input); static void _events_cb(void *data, enum Emix_Event type, void *event_info); static Eina_Bool _desklock_cb(void *data, int type, void *info); @@ -523,51 +524,75 @@ _get_ppid(pid_t pid) return ppid; } +static E_Client_Volume_Sink * +_sink_input_e_client_volume_sink_find(Emix_Sink_Input *input, pid_t *ret_pid) +{ + Eina_List *clients, *l; + E_Client *ec; + E_Client_Volume_Sink *sink = NULL; + pid_t pid; + Eina_Bool found = EINA_FALSE; + + pid = input->pid; + + EINA_LIST_FOREACH(_client_sinks, l, sink) + { + if (sink->data == input) + break; + } + + for (;;) + { + if ((pid <= 1) || (pid == getpid())) break; + clients = e_client_focus_stack_get(); + EINA_LIST_FOREACH(clients, l, ec) + { + if ((ec->netwm.pid == pid) && (!ec->parent)) + { + DBG("Sink found the client %s", + e_client_util_name_get(ec)); + if (!sink) + { + DBG("Create a new client_volume_sink"); + sink = e_client_volume_sink_new(_sink_input_get, + _sink_input_set, + _sink_input_min_get, + _sink_input_max_get, + _sink_input_name_get, + input); + } + e_client_volume_sink_append(ec, sink); + _client_sinks = eina_list_append(_client_sinks, sink); + found = EINA_TRUE; + } + } + if (found) break; + pid = _get_ppid(pid); + } + if (ret_pid) *ret_pid = pid; + return found ? sink : NULL; +} + static void _sink_input_event(int type, Emix_Sink_Input *input) { - Eina_List *clients, *l, *ll; - E_Client *ec; + Eina_List *l; E_Client_Volume_Sink *sink; - pid_t pid; - Eina_Bool found = EINA_FALSE; switch (type) { case EMIX_SINK_INPUT_ADDED_EVENT: - pid = input->pid; - for (;;) - { - if ((pid <= 1) || (pid == getpid())) return; - clients = e_client_focus_stack_get(); - EINA_LIST_FOREACH(clients, l, ec) - { - if ((ec->netwm.pid == pid) && (!ec->parent)) - { - DBG("Sink found the client %s", - e_client_util_name_get(ec)); - sink = e_client_volume_sink_new(_sink_input_get, - _sink_input_set, - _sink_input_min_get, - _sink_input_max_get, - _sink_input_name_get, - input); - e_client_volume_sink_append(ec, sink); - _client_sinks = eina_list_append(_client_sinks, sink); - found = EINA_TRUE; - } - } - if (found) break; - pid = _get_ppid(pid); - } + _sink_input_e_client_volume_sink_find(input, NULL); break; case EMIX_SINK_INPUT_REMOVED_EVENT: - EINA_LIST_FOREACH_SAFE(_client_sinks, l, ll, sink) + EINA_LIST_FOREACH(_client_sinks, l, sink) { if (sink->data == input) { + DBG("Client sink del"); e_client_volume_sink_del(sink); _client_sinks = eina_list_remove_list(_client_sinks, l); + break; } } break; @@ -953,39 +978,33 @@ _client_mixer_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, static Eina_Bool _e_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { - E_Event_Client *ev; - Eina_List *l; - Emix_Sink_Input *input; - pid_t pid; - E_Client_Volume_Sink *sink; + E_Event_Client *ev; + Eina_List *l, *ll; + Emix_Sink_Input *input; + E_Client *ec; + E_Client_Volume_Sink *sink; + pid_t pid; - ev = event; + ev = event; - if (ev->ec->parent) return ECORE_CALLBACK_PASS_ON; - EINA_LIST_FOREACH((Eina_List *)emix_sink_inputs_get(), l, input) - { - pid = input->pid; - while (42) - { - if (pid <= 1 || pid == getpid()) return ECORE_CALLBACK_PASS_ON; - if (ev->ec->netwm.pid == pid) - { - DBG("Client(%s) found a sink input", - e_client_util_name_get(ev->ec)); - sink = e_client_volume_sink_new(_sink_input_get, - _sink_input_set, - _sink_input_min_get, - _sink_input_max_get, - _sink_input_name_get, - input); - e_client_volume_sink_append(ev->ec, sink); - _client_sinks = eina_list_append(_client_sinks, sink); - return ECORE_CALLBACK_PASS_ON; - } - pid = _get_ppid(pid); - } - } - return ECORE_CALLBACK_PASS_ON; + if (ev->ec->parent) return ECORE_CALLBACK_PASS_ON; + EINA_LIST_FOREACH((Eina_List *)emix_sink_inputs_get(), l, input) + { + sink = _sink_input_e_client_volume_sink_find(input, &pid); + if (sink) + { + EINA_LIST_FOREACH_SAFE(sink->clients, l, ll, ec) + { + if (ec->netwm.pid != pid) + { + DBG("Clean invalid client sink %s", + e_client_util_name_get(ec)); + e_client_volume_sink_remove(ec, sink); + } + } + } + } + return ECORE_CALLBACK_PASS_ON; } static Eina_Bool