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
This commit is contained in:
Michaël Bouchaud (yoz) 2016-10-14 12:18:36 +02:00
parent 1943cee080
commit 06ea6cadbd
7 changed files with 275 additions and 0 deletions

View File

@ -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 \

View File

@ -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;
}

View File

@ -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);

212
src/bin/e_client_volume.c Normal file
View File

@ -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);
}

44
src/bin/e_client_volume.h Normal file
View File

@ -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

View File

@ -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"

View File

@ -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();