1 #include "e_mod_main.h"
2 #include "e_mod_system.h"
7 static void _mixer_popup_timer_new(E_Mixer_Instance *inst);
8 static Eina_Bool _mixer_popup_timer_cb(void *data);
10 static E_Module *mixer_mod = NULL;
11 static char tmpbuf[PATH_MAX]; /* general purpose buffer, just use immediately */
13 static const char _conf_domain[] = "module.mixer";
14 static const char _name[] = "mixer";
15 const char _e_mixer_Name[] = "Mixer";
16 Eina_Bool _mixer_using_default = EINA_FALSE;
17 E_Mixer_Volume_Get_Cb e_mod_mixer_volume_get;
18 E_Mixer_Volume_Set_Cb e_mod_mixer_volume_set;
19 E_Mixer_Mute_Get_Cb e_mod_mixer_mute_get;
20 E_Mixer_Mute_Set_Cb e_mod_mixer_mute_set;
21 E_Mixer_Capture_Cb e_mod_mixer_mutable_get;
22 E_Mixer_State_Get_Cb e_mod_mixer_state_get;
23 E_Mixer_Capture_Cb e_mod_mixer_capture_get;
24 E_Mixer_Cb e_mod_mixer_new;
25 E_Mixer_Cb e_mod_mixer_del;
26 E_Mixer_Cb e_mod_mixer_channel_default_name_get;
27 E_Mixer_Cb e_mod_mixer_channel_get_by_name;
28 E_Mixer_Cb e_mod_mixer_channel_name_get;
29 E_Mixer_Cb e_mod_mixer_channel_del;
30 E_Mixer_Cb e_mod_mixer_channel_free;
31 E_Mixer_Cb e_mod_mixer_channels_free;
32 E_Mixer_Cb e_mod_mixer_channels_get;
33 E_Mixer_Cb e_mod_mixer_channels_names_get;
34 E_Mixer_Cb e_mod_mixer_card_name_get;
35 E_Mixer_Cb e_mod_mixer_cards_get;
36 E_Mixer_Cb e_mod_mixer_cards_free;
37 E_Mixer_Cb e_mod_mixer_card_default_get;
40 _mixer_notify(const float val, E_Mixer_Instance *inst __UNUSED__)
44 E_Mixer_Module_Context *ctxt;
48 if (val > 100.0 || val < 0.0)
51 if (!(ctxt = (E_Mixer_Module_Context*)mixer_mod->data) || !ctxt->desktop_notification)
54 ret = snprintf(buf, (sizeof(buf) - 1), "%s: %d%%", _("New volume"), (int)(val + 0.5));
55 if ((ret < 0) || ((unsigned int)ret > sizeof(buf)))
57 //Names are taken from FDO icon naming scheme
59 icon = "audio-volume-muted";
60 else if ((val > 33.3) && (val < 66.6))
61 icon = "audio-volume-medium";
63 icon = "audio-volume-low";
65 icon = "audio-volume-high";
67 n = e_notification_full_new(_("Mixer"), 0, icon, _("Volume changed"), buf, 2000);
68 e_notification_replaces_id_set(n, EINA_TRUE);
69 e_notification_send(n, NULL, NULL);
70 e_notification_unref(n);
75 e_mixer_theme_path(void)
77 #define TF "/e-module-mixer.edj"
80 dirlen = strlen(mixer_mod->dir);
81 if (dirlen >= sizeof(tmpbuf) - sizeof(TF))
84 memcpy(tmpbuf, mixer_mod->dir, dirlen);
85 memcpy(tmpbuf + dirlen, TF, sizeof(TF));
92 _mixer_gadget_configuration_defaults(E_Mixer_Gadget_Config *conf)
95 const char *card, *channel;
97 card = e_mod_mixer_card_default_get();
101 sys = e_mod_mixer_new(card);
104 eina_stringshare_del(card);
108 channel = e_mod_mixer_channel_default_name_get(sys);
109 e_mod_mixer_del(sys);
113 eina_stringshare_del(card);
118 conf->channel_name = channel;
119 conf->lock_sliders = 1;
120 conf->show_locked = 0;
121 conf->keybindings_popup = 0;
126 static E_Mixer_Gadget_Config *
127 _mixer_gadget_configuration_new(E_Mixer_Module_Config *mod_conf, const char *id)
129 E_Mixer_Gadget_Config *conf;
131 conf = E_NEW(E_Mixer_Gadget_Config, 1);
135 if (!_mixer_gadget_configuration_defaults(conf))
141 conf->id = eina_stringshare_add(id);
142 if (!mod_conf->gadgets)
143 mod_conf->gadgets = eina_hash_string_superfast_new(NULL);
144 eina_hash_direct_add(mod_conf->gadgets, conf->id, conf);
150 _mixer_gadget_configuration_free_int(E_Mixer_Gadget_Config *conf)
153 e_object_del(E_OBJECT(conf->dialog));
156 eina_stringshare_del(conf->card);
157 if (conf->channel_name)
158 eina_stringshare_del(conf->channel_name);
160 eina_stringshare_del(conf->id);
165 _mixer_gadget_configuration_free(E_Mixer_Module_Config *mod_conf, E_Mixer_Gadget_Config *conf)
171 eina_hash_del(mod_conf->gadgets, conf->id, conf);
172 if (!eina_hash_population(mod_conf->gadgets))
173 eina_hash_free(mod_conf->gadgets);
174 _mixer_gadget_configuration_free_int(conf);
178 _mixer_gadget_configuration_free_foreach(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *hdata, void *fdata __UNUSED__)
180 _mixer_gadget_configuration_free_int(hdata);
185 _mixer_module_configuration_alert(void *data)
187 e_util_dialog_show(_("Mixer Settings Updated"), "%s", (char *)data);
188 return ECORE_CALLBACK_CANCEL;
191 static E_Mixer_Module_Config *
192 _mixer_module_configuration_new(void)
194 E_Mixer_Module_Config *conf;
196 conf = E_NEW(E_Mixer_Module_Config, 1);
204 _mixer_module_configuration_free(E_Mixer_Module_Config *conf)
209 eina_hash_foreach(conf->gadgets,
210 _mixer_gadget_configuration_free_foreach, NULL);
211 eina_hash_free(conf->gadgets);
212 eina_stringshare_del(conf->default_gc_id);
217 _mixer_popup_update(E_Mixer_Instance *inst)
219 E_Mixer_Channel_State *state;
221 state = &inst->mixer_state;
224 e_slider_value_set(inst->ui.left, state->left);
226 e_slider_value_set(inst->ui.right, state->right);
228 e_widget_check_checked_set(inst->ui.mute, state->mute);
232 _mixer_gadget_update(E_Mixer_Instance *inst)
234 Edje_Message_Int_Set *msg;
239 e_mod_mixer_state_get(inst->sys, inst->channel, &inst->mixer_state);
241 msg = alloca(sizeof(Edje_Message_Int_Set) + (2 * sizeof(int)));
243 msg->val[0] = inst->mixer_state.mute;
244 msg->val[1] = inst->mixer_state.left;
245 msg->val[2] = inst->mixer_state.right;
246 edje_object_message_send(inst->ui.gadget, EDJE_MESSAGE_INT_SET, 0, msg);
248 edje_object_signal_emit(inst->ui.gadget, "e,action,volume,change", "e");
251 _mixer_popup_update(inst);
255 _mixer_balance_left(E_Mixer_Instance *inst)
257 E_Mixer_Channel_State *state;
259 state = &inst->mixer_state;
260 e_mod_mixer_volume_get(inst->sys, inst->channel,
261 &state->left, &state->right);
262 if (state->left >= 0)
269 if (state->right >= 0)
271 if (state->right < 95)
277 e_mod_mixer_volume_set(inst->sys, inst->channel,
278 state->left, state->right);
279 _mixer_gadget_update(inst);
283 _mixer_balance_right(E_Mixer_Instance *inst)
285 E_Mixer_Channel_State *state;
287 state = &inst->mixer_state;
288 e_mod_mixer_volume_get(inst->sys, inst->channel,
289 &state->left, &state->right);
290 if (state->left >= 0)
292 if (state->left < 95)
297 if (state->right >= 0)
299 if (state->right > 5)
304 e_mod_mixer_volume_set(inst->sys, inst->channel,
305 state->left, state->right);
306 _mixer_gadget_update(inst);
310 _mixer_volume_increase(E_Mixer_Instance *inst, Eina_Bool non_ui)
312 E_Mixer_Channel_State *state;
314 state = &inst->mixer_state;
315 e_mod_mixer_volume_get(inst->sys, inst->channel,
316 &state->left, &state->right);
317 if (state->left >= 0)
319 if (state->left < 95)
325 if (state->right >= 0)
327 if (state->right < 95)
333 e_mod_mixer_volume_set(inst->sys, inst->channel,
334 state->left, state->right);
335 _mixer_gadget_update(inst);
337 _mixer_notify(((float)state->left + (float)state->right) / 2.0, inst);
341 _mixer_volume_decrease(E_Mixer_Instance *inst, Eina_Bool non_ui)
343 E_Mixer_Channel_State *state;
345 state = &inst->mixer_state;
346 e_mod_mixer_volume_get(inst->sys, inst->channel,
347 &state->left, &state->right);
348 if (state->left >= 0)
355 if (state->right >= 0)
357 if (state->right > 5)
363 e_mod_mixer_volume_set(inst->sys, inst->channel,
364 state->left, state->right);
365 _mixer_gadget_update(inst);
367 _mixer_notify(((float)state->left + (float)state->right) / 2.0, inst);
371 _mixer_toggle_mute(E_Mixer_Instance *inst, Eina_Bool non_ui)
373 E_Mixer_Channel_State *state;
375 if (!e_mod_mixer_mutable_get(inst->sys, inst->channel))
378 state = &inst->mixer_state;
379 e_mod_mixer_mute_get(inst->sys, inst->channel, &state->mute);
380 state->mute = !state->mute;
381 e_mod_mixer_mute_set(inst->sys, inst->channel, state->mute);
382 if (!state->mute) e_mod_mixer_volume_set(inst->sys, inst->channel, state->left, state->right);
383 _mixer_gadget_update(inst);
387 _mixer_notify(0.0, inst);
389 _mixer_notify(((float)state->left + (float)state->right) / 2.0, inst);
394 _mixer_popup_cb_volume_left_change(void *data, Evas_Object *obj, void *event __UNUSED__)
396 E_Mixer_Instance *inst = data;
397 E_Mixer_Channel_State *state = &inst->mixer_state;
399 e_mod_mixer_volume_get(inst->sys, inst->channel,
400 &state->left, &state->right);
402 state->left = (int)e_slider_value_get(obj);
403 if (inst->conf->lock_sliders)
405 state->right = state->left;
406 e_slider_value_set(inst->ui.right, state->right);
409 e_mod_mixer_volume_set(inst->sys, inst->channel,
410 state->left, state->right);
411 _mixer_gadget_update(inst);
415 _mixer_popup_cb_volume_right_change(void *data, Evas_Object *obj, void *event __UNUSED__)
417 E_Mixer_Instance *inst = data;
418 E_Mixer_Channel_State *state = &inst->mixer_state;
420 e_mod_mixer_volume_get(inst->sys, inst->channel,
421 &state->left, &state->right);
423 state->right = (int)e_slider_value_get(obj);
424 if (inst->conf->lock_sliders)
426 state->left = state->right;
427 e_slider_value_set(inst->ui.left, state->left);
430 e_mod_mixer_volume_set(inst->sys, inst->channel,
431 state->left, state->right);
432 _mixer_gadget_update(inst);
436 _mixer_popup_cb_mute_change(void *data, Evas_Object *obj, void *event __UNUSED__)
438 E_Mixer_Instance *inst = data;
439 E_Mixer_Channel_State *state = &inst->mixer_state;
441 state->mute = e_widget_check_checked_get(obj);
442 e_mod_mixer_mute_set(inst->sys, inst->channel, state->mute);
443 if (!state->mute) e_mod_mixer_volume_set(inst->sys, inst->channel, state->left, state->right);
445 _mixer_gadget_update(inst);
449 _mixer_popup_add_slider(E_Mixer_Instance *inst, int value, void (*cb) (void *data, Evas_Object *obj, void *event_info))
451 Evas_Object *slider = e_slider_add(inst->popup->win->evas);
452 evas_object_show(slider);
453 e_slider_orientation_set(slider, 0);
454 e_slider_value_set(slider, value);
455 e_slider_value_range_set(slider, 0.0, 100.0);
456 e_slider_value_format_display_set(slider, NULL);
457 evas_object_smart_callback_add(slider, "changed", cb, inst);
463 _mixer_app_cb_del(E_Dialog *dialog __UNUSED__, void *data)
465 E_Mixer_Module_Context *ctxt = data;
466 ctxt->mixer_dialog = NULL;
469 static void _mixer_popup_del(E_Mixer_Instance *inst);
472 _mixer_popup_input_window_mouse_up_cb(void *data, int type __UNUSED__, void *event)
474 Ecore_Event_Mouse_Button *ev = event;
475 E_Mixer_Instance *inst = data;
477 if (ev->window != inst->ui.input.win)
478 return ECORE_CALLBACK_PASS_ON;
480 _mixer_popup_del(inst);
482 return ECORE_CALLBACK_PASS_ON;
486 _mixer_popup_input_window_key_down_cb(void *data, int type __UNUSED__, void *event)
488 Ecore_Event_Key *ev = event;
489 E_Mixer_Instance *inst = data;
492 if (ev->window != inst->ui.input.win)
493 return ECORE_CALLBACK_PASS_ON;
496 if (strcmp(keysym, "Escape") == 0)
497 _mixer_popup_del(inst);
498 else if (strcmp(keysym, "Up") == 0)
499 _mixer_volume_increase(inst, EINA_FALSE);
500 else if (strcmp(keysym, "Down") == 0)
501 _mixer_volume_decrease(inst, EINA_FALSE);
502 else if ((strcmp(keysym, "Return") == 0) ||
503 (strcmp(keysym, "KP_Enter") == 0))
504 _mixer_toggle_mute(inst, EINA_FALSE);
509 E_Config_Binding_Key *bind;
510 E_Binding_Modifier mod;
511 Eina_Bool handled = EINA_FALSE;
513 for (l = e_config->key_bindings; l; l = l->next)
518 (strcmp(bind->action, "volume_increase") &&
519 strcmp(bind->action, "volume_decrease") &&
520 strcmp(bind->action, "volume_mute")))
525 if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
526 mod |= E_BINDING_MODIFIER_SHIFT;
527 if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
528 mod |= E_BINDING_MODIFIER_CTRL;
529 if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
530 mod |= E_BINDING_MODIFIER_ALT;
531 if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
532 mod |= E_BINDING_MODIFIER_WIN;
534 if (bind->key && (!strcmp(bind->key, ev->keyname)) &&
535 ((bind->modifiers == mod) || (bind->any_mod)))
537 if (!(act = e_action_find(bind->action))) continue;
538 if (act->func.go_key)
539 act->func.go_key(E_OBJECT(inst->gcc->gadcon->zone), bind->params, ev);
540 else if (act->func.go)
541 act->func.go(E_OBJECT(inst->gcc->gadcon->zone), bind->params);
545 if (!handled) _mixer_popup_del(inst);
548 return ECORE_CALLBACK_PASS_ON;
552 _mixer_popup_input_window_destroy(E_Mixer_Instance *inst)
554 e_grabinput_release(0, inst->ui.input.win);
555 ecore_x_window_free(inst->ui.input.win);
556 inst->ui.input.win = 0;
558 ecore_event_handler_del(inst->ui.input.mouse_up);
559 inst->ui.input.mouse_up = NULL;
561 ecore_event_handler_del(inst->ui.input.key_down);
562 inst->ui.input.key_down = NULL;
566 _mixer_popup_input_window_create(E_Mixer_Instance *inst)
568 Ecore_X_Window_Configure_Mask mask;
569 Ecore_X_Window w, popup_w;
572 man = e_manager_current_get();
574 w = ecore_x_window_input_new(man->root, 0, 0, man->w, man->h);
575 mask = (ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE |
576 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING);
577 popup_w = inst->popup->win->evas_win;
578 ecore_x_window_configure(w, mask, 0, 0, 0, 0, 0, popup_w,
579 ECORE_X_WINDOW_STACK_BELOW);
580 ecore_x_window_show(w);
582 inst->ui.input.mouse_up =
583 ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
584 _mixer_popup_input_window_mouse_up_cb, inst);
586 inst->ui.input.key_down =
587 ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
588 _mixer_popup_input_window_key_down_cb, inst);
590 inst->ui.input.win = w;
591 e_grabinput_get(0, 0, inst->ui.input.win);
595 _mixer_popup_del(E_Mixer_Instance *inst)
597 _mixer_popup_input_window_destroy(inst);
598 e_object_del(E_OBJECT(inst->popup));
599 inst->ui.label = NULL;
600 inst->ui.left = NULL;
601 inst->ui.right = NULL;
602 inst->ui.mute = NULL;
603 inst->ui.table = NULL;
604 inst->ui.button = NULL;
606 if (inst->popup_timer)
607 ecore_timer_del(inst->popup_timer);
608 inst->popup_timer = NULL;
612 _mixer_app_select_current(E_Dialog *dialog, E_Mixer_Instance *inst)
614 E_Mixer_Gadget_Config *conf = inst->conf;
616 e_mixer_app_dialog_select(dialog, conf->card, conf->channel_name);
621 _mixer_popup_cb_mixer(void *data, void *data2 __UNUSED__)
623 E_Mixer_Instance *inst = data;
624 E_Mixer_Module_Context *ctxt;
627 _mixer_popup_del(inst);
629 ctxt = mixer_mod->data;
630 if (ctxt->mixer_dialog)
632 _mixer_app_select_current(ctxt->mixer_dialog, inst);
633 e_dialog_show(ctxt->mixer_dialog);
637 con = e_container_current_get(e_manager_current_get());
638 ctxt->mixer_dialog = e_mixer_app_dialog_new(
639 con, _mixer_app_cb_del, ctxt);
641 _mixer_app_select_current(ctxt->mixer_dialog, inst);
645 _mixer_popup_new(E_Mixer_Instance *inst)
647 E_Mixer_Channel_State *state;
652 if (inst->conf->dialog)
655 state = &inst->mixer_state;
656 e_mod_mixer_state_get(inst->sys, inst->channel, state);
658 if ((state->right >= 0) &&
659 (inst->conf->show_locked || (!inst->conf->lock_sliders)))
664 inst->popup = e_gadcon_popup_new(inst->gcc);
665 evas = inst->popup->win->evas;
667 inst->ui.table = e_widget_table_add(evas, 0);
669 inst->ui.label = e_widget_label_add(evas, inst->conf->channel_name);
670 e_widget_table_object_append(inst->ui.table, inst->ui.label,
671 0, 0, colspan, 1, 0, 0, 0, 0);
673 if (state->left >= 0)
675 inst->ui.left = _mixer_popup_add_slider(
676 inst, state->left, _mixer_popup_cb_volume_left_change);
677 e_widget_table_object_append(inst->ui.table, inst->ui.left,
678 0, 1, 1, 1, 1, 1, 1, 1);
681 inst->ui.left = NULL;
683 if ((state->right >= 0) &&
684 (inst->conf->show_locked || (!inst->conf->lock_sliders)))
686 inst->ui.right = _mixer_popup_add_slider(
687 inst, state->right, _mixer_popup_cb_volume_right_change);
688 e_widget_table_object_append(inst->ui.table, inst->ui.right,
689 1, 1, 1, 1, 1, 1, 1, 1);
692 inst->ui.right = NULL;
694 if (e_mod_mixer_mutable_get(inst->sys, inst->channel))
696 inst->ui.mute = e_widget_check_add(evas, _("Mute"), &state->mute);
697 evas_object_show(inst->ui.mute);
698 e_widget_table_object_append(inst->ui.table, inst->ui.mute,
699 0, 2, colspan, 1, 1, 1, 1, 0);
700 evas_object_smart_callback_add(inst->ui.mute, "changed",
701 _mixer_popup_cb_mute_change, inst);
704 inst->ui.mute = NULL;
706 inst->ui.button = e_widget_button_add(evas, NULL, "preferences-system",
707 _mixer_popup_cb_mixer, inst, NULL);
708 e_widget_table_object_append(inst->ui.table, inst->ui.button,
709 0, 7, colspan, 1, 1, 1, 1, 0);
711 e_widget_size_min_get(inst->ui.table, &mw, &mh);
712 if (mh < 208) mh = 208;
713 e_widget_size_min_set(inst->ui.table, mw, mh);
715 e_gadcon_popup_content_set(inst->popup, inst->ui.table);
716 e_gadcon_popup_show(inst->popup);
717 _mixer_popup_input_window_create(inst);
721 _mixer_popup_timer_new(E_Mixer_Instance *inst)
725 if (inst->popup_timer)
727 ecore_timer_del(inst->popup_timer);
728 inst->popup_timer = ecore_timer_add(1.0, _mixer_popup_timer_cb, inst);
733 _mixer_popup_new(inst);
734 inst->popup_timer = ecore_timer_add(1.0, _mixer_popup_timer_cb, inst);
739 _mixer_popup_timer_cb(void *data)
741 E_Mixer_Instance *inst;
745 _mixer_popup_del(inst);
746 inst->popup_timer = NULL;
748 return ECORE_CALLBACK_CANCEL;
752 _mixer_menu_cb_post(void *data, E_Menu *menu __UNUSED__)
754 E_Mixer_Instance *inst = data;
755 if ((!inst) || (!inst->menu))
759 e_object_del(E_OBJECT(inst->menu));
765 _mixer_menu_cb_cfg(void *data, E_Menu *menu __UNUSED__, E_Menu_Item *mi __UNUSED__)
767 E_Mixer_Instance *inst = data;
771 _mixer_popup_del(inst);
772 con = e_container_current_get(e_manager_current_get());
773 inst->conf->dialog = e_mixer_config_dialog_new(con, inst->conf);
777 _mixer_menu_new(E_Mixer_Instance *inst, Evas_Event_Mouse_Down *ev)
784 zone = e_util_zone_current_get(e_manager_current_get());
788 mi = e_menu_item_new(m);
789 e_menu_item_label_set(mi, _("Settings"));
790 e_util_menu_item_theme_icon_set(mi, "configure");
791 e_menu_item_callback_set(mi, _mixer_menu_cb_cfg, inst);
793 m = e_gadcon_client_util_menu_items_append(inst->gcc, m, 0);
794 e_menu_post_deactivate_callback_set(m, _mixer_menu_cb_post, inst);
797 e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, NULL, NULL);
798 e_menu_activate_mouse(m, zone, x + ev->output.x, y + ev->output.y,
799 1, 1, E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
800 evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button,
801 EVAS_BUTTON_NONE, ev->timestamp, NULL);
805 _mixer_cb_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
807 E_Mixer_Instance *inst = data;
808 Evas_Event_Mouse_Down *ev = event;
813 _mixer_popup_new(inst);
815 _mixer_popup_del(inst);
817 else if (ev->button == 2)
818 _mixer_toggle_mute(inst, EINA_FALSE);
819 else if ((ev->button == 3) && (!inst->menu))
820 _mixer_menu_new(inst, ev);
824 _mixer_cb_mouse_wheel(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
826 E_Mixer_Instance *inst = data;
827 Evas_Event_Mouse_Wheel *ev = event;
829 if (ev->direction == 0)
832 _mixer_volume_decrease(inst, EINA_FALSE);
834 _mixer_volume_increase(inst, EINA_FALSE);
836 else if (_mixer_using_default && (ev->direction == 1)) /* invalid with pulse */
839 _mixer_balance_left(inst);
841 _mixer_balance_right(inst);
846 _mixer_sys_setup(E_Mixer_Instance *inst)
848 E_Mixer_Gadget_Config *conf;
851 if ((!_mixer_using_default) && (!e_mixer_pulse_ready())) return 1;
854 e_mod_mixer_del(inst->sys);
856 inst->sys = e_mod_mixer_new(conf->card);
859 inst->channel = NULL;
863 inst->channel = e_mod_mixer_channel_get_by_name(inst->sys, conf->channel_name);
864 return !!inst->channel;
868 _mixer_system_cb_update(void *data, E_Mixer_System *sys __UNUSED__)
870 E_Mixer_Instance *inst = data;
871 e_mod_mixer_state_get(inst->sys, inst->channel, &inst->mixer_state);
872 _mixer_gadget_update(inst);
878 e_mixer_update(E_Mixer_Instance *inst)
882 e_modapi_save(mixer_mod);
883 if ((!inst) || (!inst->conf))
886 r = _mixer_sys_setup(inst);
887 if (r && _mixer_using_default)
888 e_mixer_system_callback_set(inst->sys, _mixer_system_cb_update, inst);
894 _mixer_sys_setup_default_card(E_Mixer_Instance *inst)
896 E_Mixer_Gadget_Config *conf;
901 eina_stringshare_del(conf->card);
903 card = e_mod_mixer_card_default_get();
907 inst->sys = e_mod_mixer_new(card);
916 eina_stringshare_del(card);
923 _mixer_sys_setup_default_channel(E_Mixer_Instance *inst)
925 E_Mixer_Gadget_Config *conf;
926 const char *channel_name;
929 if (conf->channel_name)
930 eina_stringshare_del(conf->channel_name);
932 channel_name = e_mod_mixer_channel_default_name_get(inst->sys);
936 inst->channel = e_mod_mixer_channel_get_by_name(inst->sys, channel_name);
940 conf->channel_name = channel_name;
944 eina_stringshare_del(channel_name);
946 conf->channel_name = NULL;
951 _mixer_sys_setup_defaults(E_Mixer_Instance *inst)
953 if ((!_mixer_using_default) && (!e_mixer_pulse_ready())) return 1;
954 if ((!inst->sys) && (!_mixer_sys_setup_default_card(inst)))
957 return _mixer_sys_setup_default_channel(inst);
961 e_mod_mixer_pulse_ready(Eina_Bool ready)
963 E_Mixer_Instance *inst;
964 E_Mixer_Module_Context *ctxt;
967 if (!mixer_mod) return;
969 if (ready) e_mixer_pulse_setup();
970 else e_mixer_default_setup();
972 ctxt = mixer_mod->data;
973 EINA_LIST_FOREACH(ctxt->instances, l, inst)
975 if ((!_mixer_sys_setup(inst)) && (!_mixer_sys_setup_defaults(inst)))
978 e_mod_mixer_del(inst->sys);
979 _mixer_gadget_configuration_free(ctxt->conf, inst->conf);
983 e_mod_mixer_state_get(inst->sys, inst->channel, &inst->mixer_state);
984 _mixer_gadget_update(inst);
989 e_mod_mixer_pulse_update(void)
991 E_Mixer_Instance *inst;
992 E_Mixer_Module_Context *ctxt;
995 if (!mixer_mod) return;
997 ctxt = mixer_mod->data;
998 EINA_LIST_FOREACH(ctxt->instances, l, inst)
1000 e_mod_mixer_state_get(inst->sys, inst->channel, &inst->mixer_state);
1001 _mixer_gadget_update(inst);
1005 /* Gadcon Api Functions */
1006 static void _mixer_module_configuration_setup(E_Mixer_Module_Context *ctxt);
1008 static E_Gadcon_Client *
1009 _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
1011 E_Mixer_Instance *inst;
1012 E_Mixer_Module_Context *ctxt;
1013 E_Mixer_Gadget_Config *conf;
1018 ctxt = mixer_mod->data;
1021 _mixer_module_configuration_setup(ctxt);
1026 conf = eina_hash_find(ctxt->conf->gadgets, id);
1029 conf = _mixer_gadget_configuration_new(ctxt->conf, id);
1034 inst = E_NEW(E_Mixer_Instance, 1);
1036 conf->instance = inst;
1037 if ((!_mixer_sys_setup(inst)) && (!_mixer_sys_setup_defaults(inst)))
1040 e_mod_mixer_del(inst->sys);
1041 _mixer_gadget_configuration_free(ctxt->conf, conf);
1046 if (_mixer_using_default) e_mixer_system_callback_set(inst->sys, _mixer_system_cb_update, inst);
1048 inst->ui.gadget = edje_object_add(gc->evas);
1049 e_theme_edje_object_set(inst->ui.gadget, "base/theme/modules/mixer",
1050 "e/modules/mixer/main");
1052 inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->ui.gadget);
1053 inst->gcc->data = inst;
1055 evas_object_event_callback_add(inst->ui.gadget, EVAS_CALLBACK_MOUSE_DOWN,
1056 _mixer_cb_mouse_down, inst);
1057 evas_object_event_callback_add(inst->ui.gadget, EVAS_CALLBACK_MOUSE_WHEEL,
1058 _mixer_cb_mouse_wheel, inst);
1062 e_mod_mixer_state_get(inst->sys, inst->channel, &inst->mixer_state);
1063 _mixer_gadget_update(inst);
1066 if (!ctxt->conf->default_gc_id)
1068 ctxt->conf->default_gc_id = eina_stringshare_add(id);
1069 ctxt->default_instance = inst;
1071 else if ((!ctxt->default_instance) ||
1072 (strcmp(id, ctxt->conf->default_gc_id) == 0))
1073 ctxt->default_instance = inst;
1075 ctxt->instances = eina_list_append(ctxt->instances, inst);
1081 _gc_shutdown(E_Gadcon_Client *gcc)
1083 E_Mixer_Module_Context *ctxt;
1084 E_Mixer_Instance *inst;
1089 ctxt = mixer_mod->data;
1099 e_menu_post_deactivate_callback_set(inst->menu, NULL, NULL);
1100 e_object_del(E_OBJECT(inst->menu));
1102 evas_object_del(inst->ui.gadget);
1103 e_mod_mixer_channel_del(inst->channel);
1104 e_mod_mixer_del(inst->sys);
1106 inst->conf->instance = NULL;
1107 ctxt->instances = eina_list_remove(ctxt->instances, inst);
1109 if (ctxt->default_instance == inst)
1110 ctxt->default_instance = NULL;
1116 _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient __UNUSED__)
1118 e_gadcon_client_aspect_set(gcc, 16, 16);
1119 e_gadcon_client_min_size_set(gcc, 16, 16);
1123 _gc_label(E_Gadcon_Client_Class *client_class __UNUSED__)
1125 return (char*)_(_e_mixer_Name);
1128 static Evas_Object *
1129 _gc_icon(E_Gadcon_Client_Class *client_class __UNUSED__, Evas *evas)
1131 Evas_Object *o = edje_object_add(evas);
1132 edje_object_file_set(o, e_mixer_theme_path(), "icon");
1137 _gc_id_new(E_Gadcon_Client_Class *client_class __UNUSED__)
1139 E_Mixer_Module_Context *ctxt;
1140 Eina_List *instances;
1145 ctxt = mixer_mod->data;
1149 instances = ctxt->instances;
1150 snprintf(tmpbuf, sizeof(tmpbuf), "mixer.%d", eina_list_count(instances));
1154 static const E_Gadcon_Client_Class _gc_class =
1156 GADCON_CLIENT_CLASS_VERSION, _name,
1158 _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL,
1159 e_gadcon_site_is_not_toolbar
1161 E_GADCON_CLIENT_STYLE_PLAIN
1166 EAPI E_Module_Api e_modapi = {E_MODULE_API_VERSION, _e_mixer_Name};
1169 _mixer_cb_volume_increase(E_Object *obj __UNUSED__, const char *params __UNUSED__)
1171 E_Mixer_Module_Context *ctxt;
1176 ctxt = mixer_mod->data;
1181 if (!ctxt->default_instance)
1184 if (ctxt->default_instance->conf->keybindings_popup)
1185 _mixer_popup_timer_new(ctxt->default_instance);
1186 _mixer_volume_increase(ctxt->default_instance, EINA_TRUE);
1190 _mixer_cb_volume_decrease(E_Object *obj __UNUSED__, const char *params __UNUSED__)
1192 E_Mixer_Module_Context *ctxt;
1197 ctxt = mixer_mod->data;
1201 if (!ctxt->default_instance)
1204 if (ctxt->default_instance->conf->keybindings_popup)
1205 _mixer_popup_timer_new(ctxt->default_instance);
1206 _mixer_volume_decrease(ctxt->default_instance, EINA_TRUE);
1210 _mixer_cb_volume_mute(E_Object *obj __UNUSED__, const char *params __UNUSED__)
1212 E_Mixer_Module_Context *ctxt;
1217 ctxt = mixer_mod->data;
1221 if (!ctxt->default_instance)
1224 if (ctxt->default_instance->conf->keybindings_popup)
1225 _mixer_popup_timer_new(ctxt->default_instance);
1226 _mixer_toggle_mute(ctxt->default_instance, EINA_TRUE);
1229 static E_Config_Dialog *
1230 _mixer_module_config(E_Container *con, const char *params __UNUSED__)
1232 E_Mixer_Module_Context *ctxt;
1237 ctxt = mixer_mod->data;
1241 if (ctxt->conf_dialog)
1246 _mixer_module_configuration_setup(ctxt);
1251 ctxt->conf_dialog = e_mixer_config_module_dialog_new(con, ctxt);
1252 return ctxt->conf_dialog;
1255 static const char _reg_cat[] = "extensions";
1256 static const char _reg_item[] = "extensions/mixer";
1259 _mixer_configure_registry_register(void)
1261 e_configure_registry_category_add(_reg_cat, 90, _("Extensions"), NULL,
1262 "preferences-extensions");
1263 e_configure_registry_item_add(_reg_item, 30, _(_e_mixer_Name), NULL,
1264 "preferences-desktop-mixer",
1265 _mixer_module_config);
1269 _mixer_configure_registry_unregister(void)
1271 e_configure_registry_item_del(_reg_item);
1272 e_configure_registry_category_del(_reg_cat);
1275 static E_Config_DD *
1276 _mixer_module_configuration_descriptor_new(E_Config_DD *gadget_conf_edd)
1278 E_Config_DD *conf_edd;
1280 conf_edd = E_CONFIG_DD_NEW("Mixer_Module_Config", E_Mixer_Module_Config);
1283 E_CONFIG_VAL(conf_edd, E_Mixer_Module_Config, version, INT);
1284 E_CONFIG_VAL(conf_edd, E_Mixer_Module_Config, default_gc_id, STR);
1285 E_CONFIG_HASH(conf_edd, E_Mixer_Module_Config, gadgets, gadget_conf_edd);
1286 E_CONFIG_VAL(conf_edd, E_Mixer_Module_Config, desktop_notification, INT);
1292 _mixer_module_configuration_descriptor_free(E_Config_DD *conf_edd)
1296 E_CONFIG_DD_FREE(conf_edd);
1299 static E_Config_DD *
1300 _mixer_gadget_configuration_descriptor_new(void)
1302 E_Config_DD *conf_edd;
1304 conf_edd = E_CONFIG_DD_NEW("Mixer_Gadget_Config", E_Mixer_Gadget_Config);
1307 E_CONFIG_VAL(conf_edd, E_Mixer_Gadget_Config, lock_sliders, INT);
1308 E_CONFIG_VAL(conf_edd, E_Mixer_Gadget_Config, show_locked, INT);
1309 E_CONFIG_VAL(conf_edd, E_Mixer_Gadget_Config, keybindings_popup, INT);
1310 E_CONFIG_VAL(conf_edd, E_Mixer_Gadget_Config, card, STR);
1311 E_CONFIG_VAL(conf_edd, E_Mixer_Gadget_Config, channel_name, STR);
1317 _mixer_gadget_configuration_descriptor_free(E_Config_DD *conf_edd)
1321 E_CONFIG_DD_FREE(conf_edd);
1324 static E_Mixer_Module_Config *
1325 _mixer_module_configuration_load(E_Config_DD *module_conf_edd)
1327 E_Mixer_Module_Config *conf;
1329 conf = e_config_domain_load(_conf_domain, module_conf_edd);
1332 return _mixer_module_configuration_new();
1334 if (conf && !e_util_module_config_check (_("Mixer Module"), conf->version,
1335 MOD_CONFIG_FILE_VERSION))
1337 _mixer_module_configuration_free(conf);
1338 return _mixer_module_configuration_new();
1345 _mixer_module_configuration_setup(E_Mixer_Module_Context *ctxt)
1347 E_Config_DD *module_edd, *gadget_edd;
1349 gadget_edd = _mixer_gadget_configuration_descriptor_new();
1350 module_edd = _mixer_module_configuration_descriptor_new(gadget_edd);
1351 ctxt->gadget_conf_edd = gadget_edd;
1352 ctxt->module_conf_edd = module_edd;
1353 ctxt->conf = _mixer_module_configuration_load(module_edd);
1355 #define IFMODCFG(v) if ((ctxt->conf->version & 0xffff) < v) {
1356 #define IFMODCFGEND }
1359 ctxt->conf->desktop_notification = 1;
1362 ctxt->conf->version = MOD_CONFIG_FILE_VERSION;
1363 ctxt->desktop_notification = ctxt->conf->desktop_notification;
1366 static const char _act_increase[] = "volume_increase";
1367 static const char _act_decrease[] = "volume_decrease";
1368 static const char _act_mute[] = "volume_mute";
1369 static const char _lbl_increase[] = "Increase Volume";
1370 static const char _lbl_decrease[] = "Decrease Volume";
1371 static const char _lbl_mute[] = "Mute Volume";
1374 _mixer_actions_register(E_Mixer_Module_Context *ctxt)
1376 ctxt->actions.incr = e_action_add(_act_increase);
1377 if (ctxt->actions.incr)
1379 ctxt->actions.incr->func.go = _mixer_cb_volume_increase;
1380 e_action_predef_name_set(_(_e_mixer_Name), _(_lbl_increase),
1381 _act_increase, NULL, NULL, 0);
1384 ctxt->actions.decr = e_action_add(_act_decrease);
1385 if (ctxt->actions.decr)
1387 ctxt->actions.decr->func.go = _mixer_cb_volume_decrease;
1388 e_action_predef_name_set(_(_e_mixer_Name), _(_lbl_decrease),
1389 _act_decrease, NULL, NULL, 0);
1392 ctxt->actions.mute = e_action_add(_act_mute);
1393 if (ctxt->actions.mute)
1395 ctxt->actions.mute->func.go = _mixer_cb_volume_mute;
1396 e_action_predef_name_set(_(_e_mixer_Name), _(_lbl_mute), _act_mute,
1402 _mixer_actions_unregister(E_Mixer_Module_Context *ctxt)
1404 if (ctxt->actions.incr)
1406 e_action_predef_name_del(_(_e_mixer_Name), _(_lbl_increase));
1407 e_action_del(_act_increase);
1410 if (ctxt->actions.decr)
1412 e_action_predef_name_del(_(_e_mixer_Name), _(_lbl_decrease));
1413 e_action_del(_act_decrease);
1416 if (ctxt->actions.mute)
1418 e_action_predef_name_del(_(_e_mixer_Name), _(_lbl_mute));
1419 e_action_del(_act_mute);
1424 e_mixer_default_setup(void)
1426 e_mod_mixer_volume_get = (void*)e_mixer_system_get_volume;
1427 e_mod_mixer_volume_set = (void*)e_mixer_system_set_volume;
1428 e_mod_mixer_mute_get = (void*)e_mixer_system_get_mute;
1429 e_mod_mixer_mute_set = (void*)e_mixer_system_set_mute;
1430 e_mod_mixer_mutable_get = (void*)e_mixer_system_can_mute;
1431 e_mod_mixer_state_get = (void*)e_mixer_system_get_state;
1432 e_mod_mixer_capture_get = (void*)e_mixer_system_has_capture;
1433 e_mod_mixer_new = (void*)e_mixer_system_new;
1434 e_mod_mixer_del = (void*)e_mixer_system_del;
1435 e_mod_mixer_channel_default_name_get = (void*)e_mixer_system_get_default_channel_name;
1436 e_mod_mixer_channel_get_by_name = (void*)e_mixer_system_get_channel_by_name;
1437 e_mod_mixer_channel_name_get = (void*)e_mixer_system_get_channel_name;
1438 e_mod_mixer_channel_del = (void*)e_mixer_system_channel_del;
1439 e_mod_mixer_channels_free = (void*)e_mixer_system_free_channels;
1440 e_mod_mixer_channels_get = (void*)e_mixer_system_get_channels;
1441 e_mod_mixer_channels_names_get = (void*)e_mixer_system_get_channels_names;
1442 e_mod_mixer_card_name_get = (void*)e_mixer_system_get_card_name;
1443 e_mod_mixer_cards_get = (void*)e_mixer_system_get_cards;
1444 e_mod_mixer_cards_free = (void*)e_mixer_system_free_cards;
1445 e_mod_mixer_card_default_get = (void*)e_mixer_system_get_default_card;
1446 _mixer_using_default = EINA_TRUE;
1450 e_mixer_pulse_setup(void)
1452 e_mod_mixer_volume_get = (void*)e_mixer_pulse_get_volume;
1453 e_mod_mixer_volume_set = (void*)e_mixer_pulse_set_volume;
1454 e_mod_mixer_mute_get = (void*)e_mixer_pulse_get_mute;
1455 e_mod_mixer_mute_set = (void*)e_mixer_pulse_set_mute;
1456 e_mod_mixer_mutable_get = (void*)e_mixer_pulse_can_mute;
1457 e_mod_mixer_state_get = (void*)e_mixer_pulse_get_state;
1458 e_mod_mixer_capture_get = (void*)e_mixer_pulse_has_capture;
1459 e_mod_mixer_new = (void*)e_mixer_pulse_new;
1460 e_mod_mixer_del = (void*)e_mixer_pulse_del;
1461 e_mod_mixer_channel_default_name_get = (void*)e_mixer_pulse_get_default_channel_name;
1462 e_mod_mixer_channel_get_by_name = (void*)e_mixer_pulse_get_channel_by_name;
1463 e_mod_mixer_channel_name_get = (void*)e_mixer_pulse_get_channel_name;
1464 e_mod_mixer_channel_del = (void*)e_mixer_pulse_channel_del;
1465 e_mod_mixer_channels_free = (void*)e_mixer_pulse_free_channels;
1466 e_mod_mixer_channels_get = (void*)e_mixer_pulse_get_channels;
1467 e_mod_mixer_channels_names_get = (void*)e_mixer_pulse_get_channels_names;
1468 e_mod_mixer_card_name_get = (void*)e_mixer_pulse_get_card_name;
1469 e_mod_mixer_cards_get = (void*)e_mixer_pulse_get_cards;
1470 e_mod_mixer_cards_free = (void*)e_mixer_pulse_free_cards;
1471 e_mod_mixer_card_default_get = (void*)e_mixer_pulse_get_default_card;
1472 _mixer_using_default = EINA_FALSE;
1476 e_modapi_init(E_Module *m)
1478 E_Mixer_Module_Context *ctxt;
1480 ctxt = E_NEW(E_Mixer_Module_Context, 1);
1485 e_notification_init();
1488 _mixer_configure_registry_register();
1489 _mixer_actions_register(ctxt);
1490 e_gadcon_provider_register(&_gc_class);
1491 if (!e_mixer_pulse_init()) e_mixer_default_setup();
1492 else e_mixer_pulse_setup();
1499 _mixer_instances_free(E_Mixer_Module_Context *ctxt)
1501 while (ctxt->instances)
1503 E_Mixer_Instance *inst = ctxt->instances->data;
1504 e_object_del(E_OBJECT(inst->gcc));
1509 e_modapi_shutdown(E_Module *m)
1511 E_Mixer_Module_Context *ctxt;
1517 _mixer_instances_free(ctxt);
1519 if (ctxt->conf_dialog)
1520 e_object_del(E_OBJECT(ctxt->conf_dialog));
1522 if (ctxt->mixer_dialog)
1523 e_object_del(E_OBJECT(ctxt->mixer_dialog));
1525 _mixer_configure_registry_unregister();
1526 _mixer_actions_unregister(ctxt);
1527 e_gadcon_provider_unregister(&_gc_class);
1531 _mixer_module_configuration_free(ctxt->conf);
1532 _mixer_gadget_configuration_descriptor_free(ctxt->gadget_conf_edd);
1533 _mixer_module_configuration_descriptor_free(ctxt->module_conf_edd);
1537 e_notification_shutdown();
1546 e_modapi_save(E_Module *m)
1548 E_Mixer_Module_Context *ctxt;
1556 return e_config_domain_save(_conf_domain, ctxt->module_conf_edd, ctxt->conf);