enlightenment/src/modules/mixer/gadget/mixer.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);
}
}