yoz pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=06ea6cadbd9a77dc55165a18120989a9ff912067

commit 06ea6cadbd9a77dc55165a18120989a9ff912067
Author: MichaĆ«l Bouchaud (yoz) <[email protected]>
Date:   Fri Oct 14 12:18:36 2016 +0200

    E_Client: add an abstraction api to control volume by app
    
    This api give the possibility to add sink to an E_Client and control the 
volume
    or the mute state of the sinks associated with this E_Client.
    
    @features
---
 src/bin/Makefile.mk       |   2 +
 src/bin/e_client.c        |   5 ++
 src/bin/e_client.h        |   8 ++
 src/bin/e_client_volume.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++
 src/bin/e_client_volume.h |  44 ++++++++++
 src/bin/e_includes.h      |   1 +
 src/bin/e_main.c          |   3 +
 7 files changed, 275 insertions(+)

diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk
index f199ef0..4c91854 100644
--- a/src/bin/Makefile.mk
+++ b/src/bin/Makefile.mk
@@ -72,6 +72,7 @@ src/bin/e_bg.h \
 src/bin/e_bindings.h \
 src/bin/e_bryce.h \
 src/bin/e_client.h \
+src/bin/e_client_volume.h \
 src/bin/e_client.x \
 src/bin/e_color_dialog.h  \
 src/bin/e_color.h \
@@ -243,6 +244,7 @@ src/bin/e_bindings.c \
 src/bin/e_bryce.c \
 src/bin/e_bryce_editor.c \
 src/bin/e_client.c \
+src/bin/e_client_volume.c \
 src/bin/e_color.c \
 src/bin/e_color_dialog.c \
 src/bin/e_comp.c \
diff --git a/src/bin/e_client.c b/src/bin/e_client.c
index b2d76cb..3ed3804 100644
--- a/src/bin/e_client.c
+++ b/src/bin/e_client.c
@@ -578,6 +578,7 @@ static void
 _e_client_del(E_Client *ec)
 {
    E_Client *child;
+   E_Client_Volume_Sink *sink;
 
    ec->changed = 0;
    focus_stack = eina_list_remove(focus_stack, ec);
@@ -661,6 +662,9 @@ _e_client_del(E_Client *ec)
 
    e_comp->clients = eina_list_remove(e_comp->clients, ec);
    e_comp_object_render_update_del(ec->frame);
+
+   EINA_LIST_FREE(ec->sinks, sink)
+      sink->clients = eina_list_remove(sink->clients, ec);
 }
 
 ///////////////////////////////////////////
@@ -5113,3 +5117,4 @@ e_client_layout_cb_set(E_Client_Layout_Cb cb)
      CRI("ATTEMPTING TO OVERWRITE EXISTING CLIENT LAYOUT HOOK!!!");
    _e_client_layout_cb = cb;
 }
+
diff --git a/src/bin/e_client.h b/src/bin/e_client.h
index 981cd57..7e6e954 100644
--- a/src/bin/e_client.h
+++ b/src/bin/e_client.h
@@ -689,6 +689,13 @@ struct E_Client
 
    Eina_Stringshare *uuid;
 
+   Eina_List *sinks;
+   int volume;
+   int volume_min;
+   int volume_max;
+   unsigned char mute : 1;
+   unsigned char volume_control_enabled : 1;
+
    Eina_Bool override : 1;
    Eina_Bool input_only : 1;
    Eina_Bool dialog : 1;
@@ -747,6 +754,7 @@ E_API extern int E_EVENT_CLIENT_FULLSCREEN;
 E_API extern int E_EVENT_CLIENT_UNFULLSCREEN;
 
 
+
 EINTERN void e_client_idler_before(void);
 EINTERN Eina_Bool e_client_init(void);
 EINTERN void e_client_shutdown(void);
diff --git a/src/bin/e_client_volume.c b/src/bin/e_client_volume.c
new file mode 100644
index 0000000..af68de3
--- /dev/null
+++ b/src/bin/e_client_volume.c
@@ -0,0 +1,212 @@
+#include "e.h"
+
+E_API int E_EVENT_CLIENT_VOLUME = -1;
+E_API int E_EVENT_CLIENT_MUTE = -1;
+E_API int E_EVENT_CLIENT_UNMUTE = -1;
+
+static void
+_e_client_volume_event_simple_free(void *d EINA_UNUSED, E_Event_Client *ev)
+{
+   UNREFD(ev->ec, 3);
+   e_object_unref(E_OBJECT(ev->ec));
+   free(ev);
+}
+
+static void
+_e_client_volume_event_simple(E_Client *ec, int type)
+{
+   E_Event_Client *ev;
+
+   ev = E_NEW(E_Event_Client, 1);
+   ev->ec = ec;
+   REFD(ec, 3);
+   e_object_ref(E_OBJECT(ec));
+   ecore_event_add(type, ev,
+                   (Ecore_End_Cb)_e_client_volume_event_simple_free, NULL);
+}
+
+
+EINTERN int
+e_client_volume_init(void)
+{
+   E_EVENT_CLIENT_VOLUME = ecore_event_type_new();
+   E_EVENT_CLIENT_MUTE = ecore_event_type_new();
+   E_EVENT_CLIENT_UNMUTE = ecore_event_type_new();
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_client_volume_shutdown(void)
+{
+}
+
+E_API E_Client_Volume_Sink *
+e_client_volume_sink_new(E_Client_Volume_Sink_Get func_get, 
E_Client_Volume_Sink_Set func_set, E_Client_Volume_Sink_Min_Get func_min_get, 
E_Client_Volume_Sink_Max_Get func_max_get, void *data)
+{
+   E_Client_Volume_Sink *sink;
+
+   sink = E_NEW(E_Client_Volume_Sink, 1);
+   sink->func_set = func_set;
+   sink->func_get = func_get;
+   sink->func_min_get = func_min_get;
+   sink->func_max_get = func_max_get;
+   sink->data = data;
+
+   return sink;
+}
+
+E_API void
+e_client_volume_sink_del(E_Client_Volume_Sink *sink)
+{
+   E_Client *ec;
+
+   EINA_LIST_FREE(sink->clients, ec)
+     {
+        ec->sinks = eina_list_remove(ec->sinks, sink);
+     }
+   free(sink);
+}
+
+E_API void
+e_client_volume_sink_set(E_Client_Volume_Sink *sink, int volume, Eina_Bool 
mute)
+{
+   EINA_SAFETY_ON_NULL_RETURN(sink);
+   if (sink->func_set)
+     sink->func_set(volume, mute, sink->data);
+}
+
+E_API void
+e_client_volume_sink_get(const E_Client_Volume_Sink *sink, int *volume, 
Eina_Bool *mute)
+{
+   EINA_SAFETY_ON_NULL_RETURN(sink);
+   if (sink->func_get)
+     sink->func_get(volume, mute, sink->data);
+}
+
+E_API int
+e_client_volume_sink_min_get(const E_Client_Volume_Sink *sink)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sink, 0);
+   if (sink->func_min_get)
+     return sink->func_min_get(sink->data);
+
+   return 0;
+}
+
+E_API int
+e_client_volume_sink_max_get(const E_Client_Volume_Sink *sink)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sink, 0);
+   if (sink->func_max_get)
+     return sink->func_max_get(sink->data);
+   return 0;
+}
+
+E_API void
+e_client_volume_sink_append(E_Client *ec, E_Client_Volume_Sink *sink)
+{
+   int volume_min;
+   int volume_max;
+   int volume;
+   Eina_Bool mute;
+
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   ec->sinks = eina_list_append(ec->sinks, sink);
+   sink->clients = eina_list_append(sink->clients, ec);
+   if (ec->volume_control_enabled)
+     {
+        volume_min = e_client_volume_sink_min_get(sink);
+        if (ec->volume_min < volume_min)
+          ec->volume_min = volume_min;
+        volume_max = e_client_volume_sink_max_get(sink);
+        if (ec->volume_max > volume_max)
+          ec->volume_max = volume_max;
+        if ((ec->volume_min > ec->volume)
+            || (ec->volume_max < ec->volume))
+          e_client_volume_set(ec, ec->volume);
+        e_client_volume_sink_get(sink, &volume, &mute);
+        if ((ec->volume != volume) || (ec->mute != mute))
+          {
+             e_client_volume_sink_set(sink, ec->volume, ec->mute);
+          }
+     }
+   else
+     {
+        ec->volume_min = e_client_volume_sink_min_get(sink);
+        ec->volume_max = e_client_volume_sink_max_get(sink);
+        e_client_volume_sink_get(sink, &volume, &mute);
+        ec->volume = volume;
+        ec->mute = !!mute;
+        ec->volume_control_enabled = EINA_TRUE;
+     }
+}
+
+E_API void
+e_client_volume_sink_remove(E_Client *ec, E_Client_Volume_Sink *sink)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   ec->sinks = eina_list_remove(ec->sinks, sink);
+   sink->clients = eina_list_remove(sink->clients, ec);
+}
+
+E_API void
+e_client_volume_sink_update(E_Client_Volume_Sink *sink)
+{
+   Eina_List *l;
+   int volume;
+   Eina_Bool mute;
+   E_Client *ec;
+
+   EINA_SAFETY_ON_NULL_RETURN(sink);
+
+   e_client_volume_sink_get(sink, &volume, &mute);
+   EINA_LIST_FOREACH(sink->clients, l, ec)
+     {
+        e_client_volume_set(ec, volume);
+        e_client_volume_mute_set(ec, mute);
+     }
+}
+
+E_API void
+e_client_volume_set(E_Client *ec, int volume)
+{
+   Eina_List *l;
+   E_Client_Volume_Sink *sink;
+
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   if (volume < ec->volume_min) volume = ec->volume_min;
+   if (volume > ec->volume_max) volume = ec->volume_max;
+   if (volume == ec->volume) return;
+   ec->volume = volume;
+
+   EINA_LIST_FOREACH(ec->sinks, l, sink)
+     {
+        e_client_volume_sink_set(sink, ec->volume, ec->mute);
+     }
+
+   _e_client_volume_event_simple(ec, E_EVENT_CLIENT_VOLUME);
+}
+
+E_API void
+e_client_volume_mute_set(E_Client *ec, Eina_Bool mute)
+{
+   Eina_List *l;
+   E_Client_Volume_Sink *sink;
+
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+   if (!!mute == ec->mute) return;
+   ec->mute = !!mute;
+
+   EINA_LIST_FOREACH(ec->sinks, l, sink)
+     {
+        if (sink->func_set)
+          sink->func_set(ec->volume, ec->mute, sink->data);
+     }
+   if (mute)
+     _e_client_volume_event_simple(ec, E_EVENT_CLIENT_MUTE);
+   else
+     _e_client_volume_event_simple(ec, E_EVENT_CLIENT_UNMUTE);
+}
+
diff --git a/src/bin/e_client_volume.h b/src/bin/e_client_volume.h
new file mode 100644
index 0000000..1f66cda
--- /dev/null
+++ b/src/bin/e_client_volume.h
@@ -0,0 +1,44 @@
+#ifndef E_CLIENT_VOLUME_H_
+#define E_CLIENT_VOLUME_H_
+
+typedef struct _E_Client_Volume_Sink E_Client_Volume_Sink;
+
+typedef void (*E_Client_Volume_Sink_Get)(int *volume, Eina_Bool *mute, void 
*data);
+typedef void (*E_Client_Volume_Sink_Set)(int volume, Eina_Bool mute, void 
*data);
+typedef int (*E_Client_Volume_Sink_Min_Get)(void *data);
+typedef int (*E_Client_Volume_Sink_Max_Get)(void *data);
+
+E_API extern int E_EVENT_CLIENT_VOLUME;
+E_API extern int E_EVENT_CLIENT_MUTE;
+E_API extern int E_EVENT_CLIENT_UNMUTE;
+
+struct _E_Client_Volume_Sink
+{
+   E_Client_Volume_Sink_Get func_get;
+   E_Client_Volume_Sink_Set func_set;
+   E_Client_Volume_Sink_Min_Get func_min_get;
+   E_Client_Volume_Sink_Max_Get func_max_get;
+   void *data;
+   Eina_List *clients;
+};
+
+
+EINTERN int        e_client_volume_init(void);
+EINTERN void       e_client_volume_shutdown(void);
+
+E_API void         e_client_volume_set(E_Client *ec, int volume);
+E_API void         e_client_volume_mute_set(E_Client *ec, Eina_Bool mute);
+
+E_API Evas_Object *e_client_volume_object_add(E_Client *ec, Evas *evas);
+
+E_API E_Client_Volume_Sink *e_client_volume_sink_new(E_Client_Volume_Sink_Get 
func_get, E_Client_Volume_Sink_Set func_set, E_Client_Volume_Sink_Min_Get 
func_min_get, E_Client_Volume_Sink_Max_Get func_max_get, void *data);
+E_API void         e_client_volume_sink_del(E_Client_Volume_Sink *mixer);
+E_API void         e_client_volume_sink_set(E_Client_Volume_Sink *mixer, int 
volume, Eina_Bool mute);
+E_API void         e_client_volume_sink_get(const E_Client_Volume_Sink *mixer, 
int *volume, Eina_Bool *mute);
+E_API int          e_client_volume_sink_min_get(const E_Client_Volume_Sink 
*mixer);
+E_API int          e_client_volume_sink_max_get(const E_Client_Volume_Sink 
*mixer);
+E_API void         e_client_volume_sink_append(E_Client *ec, 
E_Client_Volume_Sink *mixer);
+E_API void         e_client_volume_sink_remove(E_Client *ec, 
E_Client_Volume_Sink *mixer);
+E_API void         e_client_volume_sink_update(E_Client_Volume_Sink *mixer);
+
+#endif
diff --git a/src/bin/e_includes.h b/src/bin/e_includes.h
index 5e4caca..c2b7c2e 100644
--- a/src/bin/e_includes.h
+++ b/src/bin/e_includes.h
@@ -14,6 +14,7 @@
 #include "e_pixmap.h"
 #include "e_comp_object.h"
 #include "e_client.h"
+#include "e_client_volume.h"
 #include "e_pointer.h"
 #include "e_config.h"
 #include "e_config_data.h"
diff --git a/src/bin/e_main.c b/src/bin/e_main.c
index 115a638..cb5d875 100644
--- a/src/bin/e_main.c
+++ b/src/bin/e_main.c
@@ -1613,6 +1613,8 @@ _e_main_screens_init(void)
 {
    TS("\tscreens: client");
    if (!e_client_init()) return 0;
+   TS("\tscreens: client volume");
+   if (!e_client_volume_init()) return 0;
    TS("\tscreens: win");
    if (!e_win_init()) return 0;
    TS("Compositor Init");
@@ -1647,6 +1649,7 @@ _e_main_screens_shutdown(void)
    e_menu_shutdown();
    e_shelf_shutdown();
    e_comp_shutdown();
+   e_client_volume_shutdown();
    e_client_shutdown();
    e_exehist_shutdown();
    e_backlight_shutdown();

-- 


Reply via email to