424 lines
12 KiB
C
424 lines
12 KiB
C
#include "mixer.h"
|
|
#include "backend.h"
|
|
|
|
typedef struct _Context Context;
|
|
struct _Context
|
|
{
|
|
char *theme;
|
|
E_Module *module;
|
|
Eina_List *instances;
|
|
E_Menu *menu;
|
|
unsigned int notification_id;
|
|
};
|
|
|
|
typedef struct _Instance Instance;
|
|
struct _Instance
|
|
{
|
|
int id;
|
|
Evas_Object *o_main;
|
|
Evas_Object *o_mixer;
|
|
Evas_Object *popup;
|
|
Evas_Object *list;
|
|
Evas_Object *slider;
|
|
Evas_Object *check;
|
|
E_Gadget_Site_Orient orient;
|
|
};
|
|
|
|
static Context *gmixer_context = NULL;
|
|
static Eina_List *_handlers = NULL;
|
|
|
|
static void
|
|
_mixer_popup_update(Instance *inst, int mute, int vol)
|
|
{
|
|
elm_check_state_set(inst->check, !!mute);
|
|
elm_slider_value_set(inst->slider, vol);
|
|
}
|
|
|
|
static void
|
|
_mixer_gadget_update(void)
|
|
{
|
|
Edje_Message_Int_Set *msg;
|
|
Instance *inst;
|
|
Eina_List *l;
|
|
const Eina_List *ll;
|
|
Elm_Object_Item *it;
|
|
|
|
EINA_LIST_FOREACH(gmixer_context->instances, l, inst)
|
|
{
|
|
msg = alloca(sizeof(Edje_Message_Int_Set) + (2 * sizeof(int)));
|
|
msg->count = 3;
|
|
|
|
if (!backend_sink_default_get())
|
|
{
|
|
msg->val[0] = EINA_FALSE;
|
|
msg->val[1] = 0;
|
|
msg->val[2] = 0;
|
|
if (inst->popup)
|
|
elm_ctxpopup_dismiss(inst->popup);
|
|
}
|
|
else
|
|
{
|
|
msg->val[0] = backend_mute_get();
|
|
msg->val[1] = backend_volume_get();
|
|
msg->val[2] = msg->val[1];
|
|
if (inst->popup)
|
|
_mixer_popup_update(inst, msg->val[0], msg->val[1]);
|
|
}
|
|
edje_object_message_send(elm_layout_edje_get(inst->o_mixer), EDJE_MESSAGE_INT_SET, 0, msg);
|
|
elm_layout_signal_emit(inst->o_mixer, "e,action,volume,change", "e");
|
|
|
|
if (inst->list)
|
|
{
|
|
EINA_LIST_FOREACH(elm_list_items_get(inst->list), ll, it)
|
|
{
|
|
if (backend_sink_default_get() == elm_object_item_data_get(it))
|
|
elm_list_item_selected_set(it, EINA_TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static Eina_Bool
|
|
_mixer_backend_changed(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
|
|
{
|
|
_mixer_gadget_update();
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
}
|
|
|
|
static void
|
|
_emixer_exec_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
{
|
|
Instance *inst = data;
|
|
|
|
elm_ctxpopup_dismiss(inst->popup);
|
|
|
|
backend_emixer_exec();
|
|
}
|
|
|
|
static void
|
|
_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj,
|
|
void *event EINA_UNUSED)
|
|
{
|
|
backend_mute_set(elm_check_state_get(obj));
|
|
}
|
|
|
|
static void
|
|
_slider_changed_cb(void *data EINA_UNUSED, Evas_Object *obj,
|
|
void *event EINA_UNUSED)
|
|
{
|
|
int val;
|
|
|
|
|
|
val = (int)elm_slider_value_get(obj);
|
|
backend_volume_set(val);
|
|
}
|
|
|
|
static void
|
|
_sink_selected_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
{
|
|
Emix_Sink *s = data;
|
|
|
|
backend_sink_default_set(s);
|
|
}
|
|
|
|
static void
|
|
_mixer_popup_dismissed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
|
|
{
|
|
Instance *inst = data;
|
|
E_FREE_FUNC(obj, evas_object_del);
|
|
inst->popup = NULL;
|
|
}
|
|
|
|
static void
|
|
_mixer_popup_deleted(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
{
|
|
Instance *inst = data;
|
|
inst->popup = NULL;
|
|
inst->list = NULL;
|
|
inst->slider = NULL;
|
|
inst->check = NULL;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_mixer_sinks_changed(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
|
|
{
|
|
Eina_List *l, *ll;
|
|
Instance *inst;
|
|
|
|
EINA_LIST_FOREACH(gmixer_context->instances, l, inst)
|
|
{
|
|
if (inst->list)
|
|
{
|
|
Elm_Object_Item *default_it = NULL;
|
|
Emix_Sink *s;
|
|
|
|
elm_list_clear(inst->list);
|
|
EINA_LIST_FOREACH((Eina_List *)emix_sinks_get(), ll, s)
|
|
{
|
|
Elm_Object_Item *it;
|
|
|
|
it = elm_list_item_append(inst->list, s->name, NULL, NULL,
|
|
_sink_selected_cb, s);
|
|
if (backend_sink_default_get() == s)
|
|
default_it = it;
|
|
}
|
|
elm_list_go(inst->list);
|
|
if (default_it)
|
|
elm_list_item_selected_set(default_it, EINA_TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
}
|
|
|
|
static void
|
|
_popup_new(Instance *inst)
|
|
{
|
|
Evas_Object *button, *list, *slider, *bx;
|
|
Emix_Sink *s;
|
|
Eina_List *l;
|
|
Elm_Object_Item *default_it = NULL;
|
|
|
|
inst->popup = elm_ctxpopup_add(e_comp->elm);
|
|
elm_object_style_set(inst->popup, "noblock");
|
|
evas_object_smart_callback_add(inst->popup, "dismissed", _mixer_popup_dismissed, inst);
|
|
evas_object_event_callback_add(inst->popup, EVAS_CALLBACK_DEL, _mixer_popup_deleted, inst);
|
|
|
|
list = elm_box_add(e_comp->elm);
|
|
elm_object_content_set(inst->popup, list);
|
|
|
|
inst->list = elm_list_add(e_comp->elm);
|
|
elm_list_mode_set(inst->list, ELM_LIST_COMPRESS);
|
|
evas_object_size_hint_align_set(inst->list, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
evas_object_size_hint_weight_set(inst->list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
evas_object_show(inst->list);
|
|
|
|
EINA_LIST_FOREACH((Eina_List *)emix_sinks_get(), l, s)
|
|
{
|
|
Elm_Object_Item *it;
|
|
|
|
it = elm_list_item_append(inst->list, s->name, NULL, NULL, _sink_selected_cb, s);
|
|
if (backend_sink_default_get() == s)
|
|
default_it = it;
|
|
}
|
|
elm_list_go(inst->list);
|
|
elm_box_pack_end(list, inst->list);
|
|
|
|
bx = elm_box_add(e_comp->elm);
|
|
elm_box_horizontal_set(bx, EINA_TRUE);
|
|
evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
|
|
evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0);
|
|
elm_box_pack_end(list, bx);
|
|
evas_object_show(bx);
|
|
|
|
slider = elm_slider_add(e_comp->elm);
|
|
inst->slider = slider;
|
|
elm_slider_span_size_set(slider, 128 * elm_config_scale_get());
|
|
elm_slider_unit_format_set(slider, "%1.0f");
|
|
elm_slider_indicator_format_set(slider, "%1.0f");
|
|
evas_object_size_hint_align_set(slider, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
evas_object_size_hint_weight_set(slider, EVAS_HINT_EXPAND, 0.0);
|
|
evas_object_show(slider);
|
|
elm_slider_min_max_set(slider, 0.0, emix_max_volume_get());
|
|
evas_object_smart_callback_add(slider, "changed", _slider_changed_cb, NULL);
|
|
elm_slider_value_set(slider, backend_volume_get());
|
|
elm_box_pack_end(bx, slider);
|
|
evas_object_show(slider);
|
|
|
|
inst->check = elm_check_add(e_comp->elm);
|
|
evas_object_size_hint_align_set(inst->check, 0.5, EVAS_HINT_FILL);
|
|
elm_object_text_set(inst->check, _("Mute"));
|
|
elm_check_state_set(inst->check, backend_mute_get());
|
|
evas_object_smart_callback_add(inst->check, "changed", _check_changed_cb,
|
|
NULL);
|
|
elm_box_pack_end(bx, inst->check);
|
|
evas_object_show(inst->check);
|
|
|
|
button = elm_button_add(e_comp->elm);
|
|
evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, 0.0);
|
|
elm_object_text_set(button, _("Mixer"));
|
|
evas_object_smart_callback_add(button, "clicked", _emixer_exec_cb, inst);
|
|
elm_box_pack_end(list, button);
|
|
evas_object_show(button);
|
|
|
|
evas_object_size_hint_min_set(list, 208, 208);
|
|
|
|
e_gadget_util_ctxpopup_place(inst->o_main, inst->popup, inst->o_mixer);
|
|
evas_object_show(inst->popup);
|
|
|
|
if (default_it)
|
|
elm_list_item_selected_set(default_it, EINA_TRUE);
|
|
}
|
|
|
|
static void
|
|
_mouse_up_cb(void *data, Evas *evas EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED, void *event)
|
|
{
|
|
Instance *inst = data;
|
|
Evas_Event_Mouse_Up *ev = event;
|
|
|
|
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
|
|
|
|
if (ev->button == 1)
|
|
{
|
|
if (inst->popup)
|
|
{
|
|
elm_ctxpopup_dismiss(inst->popup);
|
|
return;
|
|
}
|
|
_popup_new(inst);
|
|
}
|
|
else if (ev->button == 2)
|
|
{
|
|
backend_mute_set(!backend_mute_get());
|
|
}
|
|
}
|
|
|
|
static void
|
|
_mouse_wheel_cb(void *data EINA_UNUSED, Evas *evas EINA_UNUSED,
|
|
Evas_Object *obj EINA_UNUSED, void *event)
|
|
{
|
|
Evas_Event_Mouse_Wheel *ev = event;
|
|
|
|
if (ev->z > 0)
|
|
backend_volume_decrease();
|
|
else if (ev->z < 0)
|
|
backend_volume_increase();
|
|
}
|
|
|
|
static Evas_Object *
|
|
_mixer_gadget_configure(Evas_Object *g EINA_UNUSED)
|
|
{
|
|
if (e_configure_registry_exists("extensions/emix"))
|
|
{
|
|
e_configure_registry_call("extensions/emix", NULL, NULL);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
_mixer_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED)
|
|
{
|
|
Evas_Coord w, h;
|
|
Instance *inst = data;
|
|
|
|
edje_object_parts_extends_calc(elm_layout_edje_get(inst->o_mixer), 0, 0, &w, &h);
|
|
if (w < 1) w = 1;
|
|
if (h < 1) h = 1;
|
|
evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, w, h);
|
|
}
|
|
|
|
static void
|
|
_mixer_gadget_created_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
|
|
{
|
|
Instance *inst = data;
|
|
|
|
if (inst->o_main)
|
|
{
|
|
e_gadget_configure_cb_set(inst->o_main, _mixer_gadget_configure);
|
|
|
|
inst->o_mixer = elm_layout_add(inst->o_main);
|
|
E_EXPAND(inst->o_mixer);
|
|
E_FILL(inst->o_mixer);
|
|
if (inst->orient == E_GADGET_SITE_ORIENT_VERTICAL)
|
|
e_theme_edje_object_set(inst->o_mixer,
|
|
"base/theme/gadget/mixer",
|
|
"e/gadget/mixer/main_vert");
|
|
else
|
|
e_theme_edje_object_set(inst->o_mixer,
|
|
"base/theme/gadget/mixer",
|
|
"e/gadget/mixer/main");
|
|
evas_object_event_callback_add(inst->o_mixer, EVAS_CALLBACK_MOUSE_UP,
|
|
_mouse_up_cb, inst);
|
|
evas_object_event_callback_add(inst->o_mixer, EVAS_CALLBACK_MOUSE_WHEEL,
|
|
_mouse_wheel_cb, inst);
|
|
evas_object_event_callback_add(inst->o_mixer, EVAS_CALLBACK_RESIZE,
|
|
_mixer_resize_cb, inst);
|
|
elm_box_pack_end(inst->o_main, inst->o_mixer);
|
|
evas_object_show(inst->o_mixer);
|
|
if (inst->id != -1)
|
|
gmixer_context->instances = eina_list_append(gmixer_context->instances, inst);
|
|
if (inst->id == -1)
|
|
{
|
|
Edje_Message_Int_Set *msg;
|
|
|
|
msg = alloca(sizeof(Edje_Message_Int_Set) + (2 * sizeof(int)));
|
|
msg->count = 3;
|
|
msg->val[0] = EINA_FALSE;
|
|
msg->val[1] = 60;
|
|
msg->val[2] = 60;
|
|
edje_object_message_send(elm_layout_edje_get(inst->o_mixer), EDJE_MESSAGE_INT_SET, 0, msg);
|
|
elm_layout_signal_emit(inst->o_mixer, "e,action,volume,change", "e");
|
|
}
|
|
else
|
|
_mixer_gadget_update();
|
|
}
|
|
evas_object_smart_callback_del_full(obj, "gadget_created", _mixer_gadget_created_cb, data);
|
|
}
|
|
|
|
static void
|
|
mixer_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
{
|
|
Instance *inst = data;
|
|
|
|
gmixer_context->instances = eina_list_remove(gmixer_context->instances, inst);
|
|
free(inst);
|
|
}
|
|
|
|
EINTERN Evas_Object *
|
|
mixer_gadget_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
|
|
{
|
|
Instance *inst;
|
|
|
|
if (*id != -1)
|
|
{
|
|
if (!mixer_init())
|
|
return NULL;
|
|
}
|
|
inst = E_NEW(Instance, 1);
|
|
inst->o_main = elm_box_add(parent);
|
|
inst->orient = orient;
|
|
inst->id = *id;
|
|
evas_object_show(inst->o_main);
|
|
|
|
evas_object_smart_callback_add(parent, "gadget_created", _mixer_gadget_created_cb, inst);
|
|
if (*id != -1)
|
|
evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_DEL, mixer_del, inst);
|
|
return inst->o_main;
|
|
}
|
|
|
|
EINTERN Eina_Bool
|
|
mixer_init(void)
|
|
{
|
|
char buf[4096];
|
|
|
|
if (!gmixer_context)
|
|
{
|
|
gmixer_context = E_NEW(Context, 1);
|
|
|
|
snprintf(buf, sizeof(buf), "%s/mixer.edj",
|
|
e_module_dir_get(gmixer_context->module));
|
|
gmixer_context->theme = strdup(buf);
|
|
E_LIST_HANDLER_APPEND(_handlers, E_EVENT_MIXER_BACKEND_CHANGED,
|
|
_mixer_backend_changed, NULL);
|
|
E_LIST_HANDLER_APPEND(_handlers, E_EVENT_MIXER_SINKS_CHANGED,
|
|
_mixer_sinks_changed, NULL);
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
EINTERN void
|
|
mixer_shutdown(void)
|
|
{
|
|
E_FREE_LIST(_handlers, ecore_event_handler_del);
|
|
if (gmixer_context)
|
|
{
|
|
free(gmixer_context->theme);
|
|
E_FREE(gmixer_context);
|
|
}
|
|
}
|
|
|