diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk index f199ef0d7..4c9185400 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 b2d76cb95..3ed3804dd 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 981cd57e6..7e6e95414 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 000000000..af68de3f4 --- /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 000000000..1f66cdaa7 --- /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 5e4caca47..c2b7c2e8d 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 115a6387d..cb5d875a2 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();