fix leak in randr2 when matching clone modes

This commit is contained in:
Carsten Haitzler 2015-06-08 20:53:13 +09:00
parent bc595f3d74
commit d17851f714
18 changed files with 1 additions and 6934 deletions

View File

@ -795,6 +795,7 @@ again:
mcommon = m;
}
}
modes = eina_list_free(modes);
// no common mode with least difference found
if (!mcommon) return;
// we have a common mode - apply it to the base screen

View File

@ -1,95 +0,0 @@
#ifndef PULSE_H
#define PULSE_H
#include <Eina.h>
#include <inttypes.h>
# ifdef EINTERN
# undef EINTERN
# endif
# ifdef __GNUC__
# if __GNUC__ >= 4
# define EINTERN __attribute__ ((visibility("hidden")))
# else
# define EINTERN
# endif
# else
# define EINTERN
# endif
#define PULSE_SUCCESS (void*)1
extern int PULSE_EVENT_CONNECTED;
extern int PULSE_EVENT_DISCONNECTED;
extern int PULSE_EVENT_CHANGE;
typedef struct Pulse Pulse;
typedef uint32_t Pulse_Tag_Id;
typedef struct Pulse_Sink Pulse_Sink;
typedef struct Pulse_Sink Pulse_Source;
typedef void (*Pulse_Cb)(Pulse *, Pulse_Tag_Id, void *);
typedef struct Pulse_Sink_Port_Info {
const char *name; /**< Name of this port */
const char *description; /**< Description of this port */
uint32_t priority; /**< The higher this value is the more useful this port is as a default */
} Pulse_Sink_Port_Info;
typedef struct Pulse_Server_Info
{
Pulse *conn;
const char *name;
const char *version;
const char *username;
const char *hostname;
const char *default_sink;
const char *default_source;
} Pulse_Server_Info;
EINTERN int pulse_init(void);
EINTERN void pulse_shutdown(void);
EINTERN Pulse *pulse_new(void);
EINTERN Eina_Bool pulse_connect(Pulse *conn);
EINTERN void pulse_disconnect(Pulse *conn);
EINTERN void pulse_free(Pulse *conn);
EINTERN void pulse_cb_set(Pulse *conn, uint32_t tagnum, Pulse_Cb cb);
EINTERN void pulse_server_info_free(Pulse_Server_Info *ev);
EINTERN uint32_t pulse_server_info_get(Pulse *conn);
EINTERN uint32_t pulse_cards_get(Pulse *conn);
#define pulse_sinks_get(conn) pulse_types_get((conn), EINA_FALSE)
#define pulse_sources_get(conn) pulse_types_get((conn), EINA_TRUE)
EINTERN uint32_t pulse_types_get(Pulse *conn, Eina_Bool source);
#define pulse_sink_get(conn, idx) pulse_type_get((conn), (idx), EINA_FALSE)
#define pulse_source_get(conn, idx) pulse_type_get((conn), (idx), EINA_FALSE)
EINTERN uint32_t pulse_type_get(Pulse *conn, uint32_t idx, Eina_Bool source);
#define pulse_sink_mute_set(conn, idx, mute) pulse_type_mute_set((conn), (idx), (mute), EINA_FALSE)
#define pulse_source_mute_set(conn, idx, mute) pulse_type_mute_set((conn), (idx), (mute), EINA_TRUE)
EINTERN uint32_t pulse_type_mute_set(Pulse *conn, uint32_t idx, Eina_Bool mute, Eina_Bool source);
#define pulse_sink_volume_set(conn, idx, channels, vol) pulse_type_volume_set((conn), (idx), (channels), (vol), EINA_FALSE)
#define pulse_source_volume_set(conn, idx, channels, vol) pulse_type_volume_set((conn), (idx), (channels), (vol), EINA_TRUE)
EINTERN uint32_t pulse_type_volume_set(Pulse *conn, uint32_t sink_num, uint8_t channels, double vol, Eina_Bool source);
EINTERN void pulse_sink_free(Pulse_Sink *sink);
EINTERN const char *pulse_sink_name_get(Pulse_Sink *sink);
EINTERN const char *pulse_sink_desc_get(Pulse_Sink *sink);
EINTERN uint32_t pulse_sink_idx_get(Pulse_Sink *sink);
EINTERN Eina_Bool pulse_sink_muted_get(Pulse_Sink *sink);
EINTERN double pulse_sink_avg_get_pct(Pulse_Sink *sink);
EINTERN float pulse_sink_balance_get(Pulse_Sink *sink);
EINTERN uint8_t pulse_sink_channels_count(Pulse_Sink *sink);
EINTERN Eina_List *pulse_sink_channel_names_get(Pulse_Sink *sink);
EINTERN Eina_Bool pulse_sinks_watch(Pulse *conn);
EINTERN const Eina_List *pulse_sink_ports_get(Pulse_Sink *sink);
EINTERN const char *pulse_sink_port_active_get(Pulse_Sink *sink);
#define pulse_source_channel_volume_set pulse_sink_channel_volume_set
EINTERN uint32_t pulse_sink_channel_volume_set(Pulse *conn, Pulse_Sink *sink, uint32_t id, double vol);
EINTERN uint32_t pulse_sink_port_set(Pulse *conn, Pulse_Sink *sink, const char *port);
EINTERN double pulse_sink_channel_volume_get(Pulse_Sink *sink, unsigned int id);
EINTERN float pulse_sink_channel_balance_get(Pulse_Sink *sink, unsigned int id);
EINTERN float pulse_sink_channel_depth_get(Pulse_Sink *sink, unsigned int id);
EINTERN unsigned int pulse_sink_channel_name_get_id(Pulse_Sink *sink, const char *name);
EINTERN const char *pulse_sink_channel_id_get_name(Pulse_Sink *sink, unsigned int id);
#endif

View File

@ -1,562 +0,0 @@
#include "e_mod_main.h"
extern const char _e_mixer_Name[];
typedef struct E_Mixer_App_Dialog_Data
{
E_Mixer_System *sys;
const char *sys_card_name;
const char *channel_name;
int lock_sliders;
Eina_List *cards;
Eina_List *channel_infos;
E_Mixer_Channel_Info *channel_info;
E_Mixer_Channel_State state;
struct e_mixer_app_ui
{
Evas_Object *hlayout;
struct e_mixer_app_ui_cards
{
Evas_Object *frame;
Evas_Object *list;
} cards;
struct e_mixer_app_ui_channels
{
Evas_Object *frame;
Evas_Object *list;
} channels;
struct e_mixer_app_ui_channel_editor
{
Evas_Object *frame;
Evas_Object *label_card;
Evas_Object *card;
Evas_Object *label_channel;
Evas_Object *channel;
Evas_Object *label_type;
Evas_Object *type;
Evas_Object *label_left;
Evas_Object *left;
Evas_Object *label_right;
Evas_Object *right;
Evas_Object *mute;
Evas_Object *lock_sliders;
} channel_editor;
} ui;
struct
{
void *data;
void (*func)(E_Dialog *dialog, void *data);
} del;
} E_Mixer_App_Dialog_Data;
static void
_cb_changed_left(void *data, Evas_Object *obj EINA_UNUSED)
{
E_Mixer_App_Dialog_Data *app = data;
E_Mixer_Channel_State *state;
state = &app->state;
if (app->lock_sliders && (state->left != state->right))
{
state->right = state->left;
e_widget_slider_value_int_set(app->ui.channel_editor.right,
state->right);
}
e_mod_mixer_volume_set(app->sys, app->channel_info,
state->left, state->right);
}
static void
_cb_changed_right(void *data, Evas_Object *obj EINA_UNUSED)
{
E_Mixer_App_Dialog_Data *app = data;
E_Mixer_Channel_State *state;
state = &app->state;
if (app->lock_sliders && (state->right != state->left))
{
state->left = state->right;
e_widget_slider_value_int_set(app->ui.channel_editor.left,
state->left);
}
e_mod_mixer_volume_set(app->sys, app->channel_info,
state->left, state->right);
}
static void
_cb_changed_mute(void *data, Evas_Object *obj EINA_UNUSED)
{
E_Mixer_App_Dialog_Data *app = data;
e_mod_mixer_mute_set(app->sys, app->channel_info, app->state.mute);
}
static void
_cb_changed_lock_sliders(void *data, Evas_Object *obj EINA_UNUSED)
{
E_Mixer_App_Dialog_Data *app = data;
E_Mixer_Channel_State *state;
if (!app->lock_sliders)
return;
state = &app->state;
if (state->left == state->right)
return;
state->left = state->right = (state->left + state->right) / 2;
e_widget_slider_value_int_set(app->ui.channel_editor.left, state->left);
e_widget_slider_value_int_set(app->ui.channel_editor.right, state->right);
e_mod_mixer_volume_set(app->sys, app->channel_info,
state->left, state->right);
}
static void
_disable_channel_editor(E_Mixer_App_Dialog_Data *app)
{
struct e_mixer_app_ui_channel_editor *ui = &app->ui.channel_editor;
e_widget_entry_text_set(ui->card, "");
e_widget_entry_text_set(ui->channel, "");
e_widget_entry_text_set(ui->type, "");
e_widget_slider_value_int_set(ui->left, 0);
e_widget_slider_value_int_set(ui->right, 0);
e_widget_check_checked_set(ui->mute, 0);
e_widget_check_checked_set(ui->lock_sliders, 0);
e_widget_disabled_set(ui->left, 1);
e_widget_disabled_set(ui->right, 1);
e_widget_disabled_set(ui->mute, 1);
e_widget_disabled_set(ui->lock_sliders, 1);
}
static void
_update_channel_editor_state(E_Mixer_App_Dialog_Data *app, const E_Mixer_Channel_State state)
{
struct e_mixer_app_ui_channel_editor *ui = &app->ui.channel_editor;
if (!e_mod_mixer_channel_has_no_volume(app->channel_info))
{
if (e_mod_mixer_channel_is_mono(app->channel_info))
e_widget_slider_value_int_set(ui->left, state.left);
else
{
e_widget_slider_value_int_set(ui->left, state.left);
e_widget_slider_value_int_set(ui->right, state.right);
}
}
if (e_mod_mixer_channel_is_mutable(app->channel_info))
e_widget_check_checked_set(ui->mute, state.mute);
}
static void
_populate_channel_editor(E_Mixer_App_Dialog_Data *app)
{
struct e_mixer_app_ui_channel_editor *ui = &app->ui.channel_editor;
E_Mixer_Channel_State state;
if ((!app->sys_card_name) || (!app->channel_name))
{
_disable_channel_editor(app);
return;
}
e_widget_entry_text_set(ui->card, app->sys_card_name);
e_widget_entry_text_set(ui->channel, app->channel_name);
if (e_mod_mixer_channel_is_boost(app->channel_info))
e_widget_entry_text_set(ui->type, _("Boost"));
else if (e_mod_mixer_channel_has_playback(app->channel_info))
e_widget_entry_text_set(ui->type, _("Playback"));
else if (e_mod_mixer_channel_has_capture(app->channel_info))
e_widget_entry_text_set(ui->type, _("Capture"));
else
e_widget_entry_text_set(ui->type, _("Switch"));
e_mod_mixer_state_get(app->sys, app->channel_info, &state);
_update_channel_editor_state(app, state);
if (e_mod_mixer_channel_is_mutable(app->channel_info))
{
e_widget_disabled_set(ui->mute, 0);
}
else
{
e_widget_disabled_set(ui->mute, 1);
e_widget_check_checked_set(ui->mute, 0);
}
if (e_mod_mixer_channel_has_no_volume(app->channel_info))
{
app->lock_sliders = 1;
e_widget_slider_value_int_set(ui->left, 0);
e_widget_slider_value_int_set(ui->right, 0);
e_widget_disabled_set(ui->lock_sliders, 1);
e_widget_disabled_set(ui->left, 1);
e_widget_disabled_set(ui->right, 1);
}
else if (e_mod_mixer_channel_is_mono(app->channel_info))
{
app->lock_sliders = 0;
e_widget_slider_value_int_set(ui->right, 0);
e_widget_disabled_set(ui->lock_sliders, 1);
e_widget_disabled_set(ui->left, 0);
e_widget_disabled_set(ui->right, 1);
}
else
{
app->lock_sliders = (state.left == state.right);
e_widget_disabled_set(ui->lock_sliders, 0);
e_widget_disabled_set(ui->left, 0);
e_widget_disabled_set(ui->right, 0);
}
e_widget_check_checked_set(ui->lock_sliders, app->lock_sliders);
}
static void
_cb_channel_selected(void *data)
{
E_Mixer_Channel_Info *info = data;
E_Mixer_App_Dialog_Data *app;
app = info->app;
app->channel_info = info;
_populate_channel_editor(app);
}
static int
_cb_system_update(void *data, E_Mixer_System *sys EINA_UNUSED)
{
E_Mixer_App_Dialog_Data *app = data;
E_Mixer_Channel_State state;
if ((!app->sys) || (!app->channel_info))
return 1;
e_mod_mixer_state_get(app->sys, app->channel_info, &state);
_update_channel_editor_state(app, state);
return 1;
}
static void
_populate_channels(E_Mixer_App_Dialog_Data *app)
{
Eina_List *l;
Evas_Object *ilist;
int header_input;
int i, selected;
ilist = app->ui.channels.list;
edje_freeze();
e_widget_ilist_freeze(ilist);
e_widget_ilist_clear(ilist);
if (app->sys)
e_mod_mixer_del(app->sys);
app->sys = e_mod_mixer_new(app->sys_card_name);
if (_mixer_using_default)
e_mixer_system_callback_set(app->sys, _cb_system_update, app);
if (app->channel_infos)
e_mod_mixer_channel_infos_free(app->channel_infos);
app->channel_infos = e_mod_mixer_channel_infos_get(app->sys);
i = 0;
selected = 0;
header_input = 0;
for (l = app->channel_infos; l; l = l->next, i++)
{
E_Mixer_Channel_Info *info = l->data;
if (header_input != e_mod_mixer_channel_group_get(info))
{
if (e_mod_mixer_channel_is_boost(info))
e_widget_ilist_header_append(ilist, NULL, _("Boost"));
else if (e_mod_mixer_channel_has_playback(info))
e_widget_ilist_header_append(ilist, NULL, _("Playback"));
else if (e_mod_mixer_channel_has_capture(info))
e_widget_ilist_header_append(ilist, NULL, _("Capture"));
else
e_widget_ilist_header_append(ilist, NULL, _("Switch"));
header_input = e_mod_mixer_channel_group_get(info);
i++;
}
info->app = app;
e_widget_ilist_append(ilist, NULL, info->name, _cb_channel_selected,
info, info->name);
if ((selected == 0) && app->channel_name && info->name &&
(strcmp(app->channel_name, info->name) == 0))
{
e_widget_ilist_selected_set(ilist, i);
app->channel_info = info;
selected = 1;
}
}
if ((selected == 0) && (i > 0))
e_widget_ilist_selected_set(ilist, 0);
else
app->channel_name = NULL;
e_widget_ilist_go(ilist);
e_widget_ilist_thaw(ilist);
edje_thaw();
}
static void
_cb_card_selected(void *data)
{
_populate_channels(data);
}
static void
_create_cards(E_Dialog *dialog EINA_UNUSED, Evas *evas, E_Mixer_App_Dialog_Data *app)
{
struct e_mixer_app_ui_cards *ui = &app->ui.cards;
const char *card;
Eina_List *l;
app->cards = e_mod_mixer_card_names_get();
if (eina_list_count(app->cards) < 2)
return;
ui->list = e_widget_ilist_add(evas, 32, 32, &app->sys_card_name);
e_widget_size_min_set(ui->list, 180, 100);
e_widget_ilist_go(ui->list);
EINA_LIST_FOREACH(app->cards, l, card)
{
const char *card_name;
card_name = e_mod_mixer_card_name_get(card);
if (!card_name)
continue;
e_widget_ilist_append(ui->list, NULL, card_name, _cb_card_selected,
app, card);
eina_stringshare_del(card_name);
}
ui->frame = e_widget_framelist_add(evas, _("Cards"), 0);
e_widget_framelist_object_append(ui->frame, ui->list);
e_widget_list_object_append(app->ui.hlayout, ui->frame, 1, 0, 0.0);
}
static void
_create_channels(E_Dialog *dialog EINA_UNUSED, Evas *evas, E_Mixer_App_Dialog_Data *app)
{
struct e_mixer_app_ui_channels *ui = &app->ui.channels;
ui->list = e_widget_ilist_add(evas, 24, 24, &app->channel_name);
e_widget_size_min_set(ui->list, 180, 100);
e_widget_ilist_go(ui->list);
ui->frame = e_widget_framelist_add(evas, _("Channels"), 0);
e_widget_framelist_object_append(ui->frame, ui->list);
e_widget_list_object_append(app->ui.hlayout, ui->frame, 1, 1, 0.0);
}
static void
_create_channel_editor(E_Dialog *dialog, Evas *evas, E_Mixer_App_Dialog_Data *app)
{
struct e_mixer_app_ui_channel_editor *ui = &app->ui.channel_editor;
ui->label_card = e_widget_label_add(evas, _("Card:"));
ui->card = e_widget_entry_add(dialog->win, NULL, NULL, NULL, NULL);
e_widget_entry_readonly_set(ui->card, 1);
ui->label_channel = e_widget_label_add(evas, _("Channel:"));
ui->channel = e_widget_entry_add(dialog->win, NULL, NULL, NULL, NULL);
e_widget_entry_readonly_set(ui->channel, 1);
ui->label_type = e_widget_label_add(evas, _("Type:"));
ui->type = e_widget_entry_add(dialog->win, NULL, NULL, NULL, NULL);
e_widget_entry_readonly_set(ui->type, 1);
ui->label_left = e_widget_label_add(evas, _("Left:"));
ui->left = e_widget_slider_add(evas, 1, 0, "%3.0f", 0.0, 100.0, 10.0, 100.0,
NULL, &app->state.left, 150);
e_widget_on_change_hook_set(ui->left, _cb_changed_left, app);
ui->label_right = e_widget_label_add(evas, _("Right:"));
ui->right = e_widget_slider_add(evas, 1, 0, "%3.0f", 0.0, 100.0, 10.0, 100.0,
NULL, &app->state.right, 150);
e_widget_on_change_hook_set(ui->right, _cb_changed_right, app);
ui->mute = e_widget_check_add(evas, _("Mute"), &app->state.mute);
e_widget_on_change_hook_set(ui->mute, _cb_changed_mute, app);
ui->lock_sliders = e_widget_check_add(evas, _("Lock Sliders"),
&app->lock_sliders);
e_widget_on_change_hook_set(ui->lock_sliders, _cb_changed_lock_sliders, app);
ui->frame = e_widget_framelist_add(evas, _("Edit"), 0);
e_widget_framelist_object_append(ui->frame, ui->label_card);
e_widget_framelist_object_append(ui->frame, ui->card);
e_widget_framelist_object_append(ui->frame, ui->label_channel);
e_widget_framelist_object_append(ui->frame, ui->channel);
e_widget_framelist_object_append(ui->frame, ui->label_type);
e_widget_framelist_object_append(ui->frame, ui->type);
e_widget_framelist_object_append(ui->frame, ui->label_left);
e_widget_framelist_object_append(ui->frame, ui->left);
e_widget_framelist_object_append(ui->frame, ui->label_right);
e_widget_framelist_object_append(ui->frame, ui->right);
e_widget_framelist_object_append(ui->frame, ui->mute);
e_widget_framelist_object_append(ui->frame, ui->lock_sliders);
e_widget_list_object_append(app->ui.hlayout, ui->frame, 1, 1, 0.5);
}
static void
_create_ui(E_Dialog *dialog, E_Mixer_App_Dialog_Data *app)
{
struct e_mixer_app_ui *ui = &app->ui;
Evas *evas;
int mw, mh;
evas = evas_object_evas_get(dialog->win);
ui->hlayout = e_widget_list_add(evas, 0, 1);
_create_cards(dialog, evas, app);
_create_channels(dialog, evas, app);
_create_channel_editor(dialog, evas, app);
e_widget_size_min_get(ui->hlayout, &mw, &mh);
if (mw < 300)
mw = 300;
if (mh < 200)
mh = 200;
e_dialog_content_set(dialog, ui->hlayout, mw, mh);
}
static void
_mixer_app_dialog_del(E_Dialog *dialog, E_Mixer_App_Dialog_Data *app)
{
if (!app)
return;
if (app->del.func)
app->del.func(dialog, app->del.data);
if ((!app->ui.cards.list) && (app->ui.channels.list))
eina_stringshare_del(app->sys_card_name);
if (app->cards)
e_mod_mixer_card_names_free(app->cards);
if (app->channel_infos)
e_mod_mixer_channel_infos_free(app->channel_infos);
e_mod_mixer_del(app->sys);
e_util_defer_object_del(E_OBJECT(dialog));
dialog->data = NULL;
E_FREE(app);
}
static void
_cb_win_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Dialog *dialog = data;
E_Mixer_App_Dialog_Data *app = dialog->data;
_mixer_app_dialog_del(dialog, app);
}
static void
_cb_dialog_dismiss(void *data, E_Dialog *dialog)
{
_mixer_app_dialog_del(dialog, data);
}
E_Dialog *
e_mixer_app_dialog_new(Evas_Object *parent EINA_UNUSED, void (*func)(E_Dialog *dialog, void *data), void *data)
{
E_Mixer_App_Dialog_Data *app;
E_Dialog *dialog;
dialog = e_dialog_new(NULL, _e_mixer_Name, "e_mixer_app_dialog");
if (!dialog)
return NULL;
app = E_NEW(E_Mixer_App_Dialog_Data, 1);
if (!app)
{
e_object_del(E_OBJECT(dialog));
return NULL;
}
dialog->data = app;
app->del.data = data;
app->del.func = func;
e_dialog_title_set(dialog, _(_e_mixer_Name));
evas_object_event_callback_add(dialog->win, EVAS_CALLBACK_DEL, _cb_win_del, dialog);
_create_ui(dialog, app);
e_dialog_button_add(dialog, _("Close"), NULL, _cb_dialog_dismiss, app);
e_dialog_button_focus_num(dialog, 1);
elm_win_center(dialog->win, 1, 1);
e_dialog_show(dialog);
e_dialog_border_icon_set(dialog, "preferences-desktop-mixer");
// FIXME: what if module unloaded while mixer_app dialog up? bad!
return dialog;
}
int
e_mixer_app_dialog_select(E_Dialog *dialog, const char *sys_card_name, const char *channel_name)
{
int n, i;
Eina_List *l;
E_Mixer_App_Dialog_Data *app;
if (!dialog)
return 0;
if ((!sys_card_name) || (!channel_name))
return 0;
app = dialog->data;
if (!app)
return 0;
n = -1;
for (i = 0, l = app->cards; l; i++, l = l->next)
{
if (strcmp(sys_card_name, l->data) == 0)
{
n = i;
break;
}
}
if (n < 0)
{
/* FIXME device disappeared, very bad !! */
return 0;
}
/* app->channel_name will be overriden by selection in _populate_channels */
app->channel_name = channel_name;
if (app->ui.cards.list)
e_widget_ilist_selected_set(app->ui.cards.list, n);
else if (app->ui.channels.list)
{
app->sys_card_name = eina_stringshare_add(sys_card_name);
_populate_channels(app);
}
return 1;
}

View File

@ -1,392 +0,0 @@
#include "e_mod_main.h"
extern const char _e_mixer_Name[];
struct _E_Config_Dialog_Data
{
int lock_sliders;
int show_locked;
int keybindings_popup;
int card_num;
int channel;
const char *card;
const char *channel_name;
Eina_List *cards;
Eina_List *card_names;
Eina_List *channel_names;
struct mixer_config_ui
{
Evas_Object *table;
struct mixer_config_ui_general
{
Evas_Object *frame;
Evas_Object *lock_sliders;
Evas_Object *show_locked;
Evas_Object *keybindings_popup;
} general;
struct mixer_config_ui_cards
{
Evas_Object *frame;
E_Radio_Group *radio;
} cards;
struct mixer_config_ui_channels
{
Evas_Object *frame;
Evas_Object *scroll;
Evas_Object *list;
E_Radio_Group *radio;
Eina_List *radios;
} channels;
} ui;
E_Mixer_Gadget_Config *conf;
};
static void
_mixer_fill_card_infos(E_Config_Dialog_Data *cfdata)
{
const char *card;
const char *name;
Eina_List *l;
int i = 0;
cfdata->card_num = -1;
cfdata->cards = e_mod_mixer_card_names_get();
cfdata->card_names = NULL;
EINA_LIST_FOREACH(cfdata->cards, l, card)
{
name = e_mod_mixer_card_name_get(card);
if ((cfdata->card_num < 0) && card && cfdata->card &&
(strcmp(card, cfdata->card) == 0))
cfdata->card_num = i;
cfdata->card_names = eina_list_append(cfdata->card_names, name);
i++;
}
if (cfdata->card_num < 0)
{
card = eina_list_nth(cfdata->cards, 0);
if (card)
{
cfdata->card_num = 0;
eina_stringshare_del(cfdata->card);
cfdata->card = eina_stringshare_ref(card);
}
}
}
static void
_mixer_fill_channel_infos(E_Config_Dialog_Data *cfdata)
{
E_Mixer_System *sys;
const char *channel;
Eina_List *l;
int i = 0;
sys = e_mod_mixer_new(cfdata->card);
if (!sys)
return;
cfdata->channel = 0;
cfdata->channel_name = eina_stringshare_add(cfdata->conf->channel_name);
cfdata->channel_names = e_mod_mixer_channel_names_get(sys);
EINA_LIST_FOREACH(cfdata->channel_names, l, channel)
{
if (channel && cfdata->channel_name &&
(channel == cfdata->channel_name ||
strcmp(channel, cfdata->channel_name) == 0))
{
cfdata->channel = i;
break;
}
i++;
}
e_mod_mixer_del(sys);
}
static void *
_create_data(E_Config_Dialog *dialog)
{
E_Config_Dialog_Data *cfdata;
E_Mixer_Gadget_Config *conf;
cfdata = E_NEW(E_Config_Dialog_Data, 1);
if (!cfdata)
return NULL;
conf = dialog->data;
cfdata->conf = conf;
cfdata->lock_sliders = conf->lock_sliders;
cfdata->show_locked = conf->show_locked;
cfdata->keybindings_popup = conf->keybindings_popup;
cfdata->card = eina_stringshare_add(conf->card);
_mixer_fill_card_infos(cfdata);
_mixer_fill_channel_infos(cfdata);
return cfdata;
}
static void
_free_data(E_Config_Dialog *dialog, E_Config_Dialog_Data *cfdata)
{
E_Mixer_Gadget_Config *conf = dialog->data;
const char *card;
if (conf)
conf->dialog = NULL;
if (!cfdata)
return;
EINA_LIST_FREE(cfdata->card_names, card)
eina_stringshare_del(card);
if (cfdata->channel_names)
e_mod_mixer_channel_names_free(cfdata->channel_names);
if (cfdata->cards)
e_mod_mixer_card_names_free(cfdata->cards);
eina_stringshare_del(cfdata->card);
eina_stringshare_del(cfdata->channel_name);
eina_list_free(cfdata->ui.channels.radios);
E_FREE(cfdata);
}
static int
_basic_apply(E_Config_Dialog *dialog, E_Config_Dialog_Data *cfdata)
{
E_Mixer_Gadget_Config *conf = dialog->data;
const char *card, *channel;
conf->lock_sliders = cfdata->lock_sliders;
conf->show_locked = cfdata->show_locked;
conf->keybindings_popup = cfdata->keybindings_popup;
conf->using_default = EINA_FALSE;
card = eina_list_nth(cfdata->cards, cfdata->card_num);
if (card)
{
eina_stringshare_del(conf->card);
conf->card = eina_stringshare_ref(card);
}
channel = eina_list_nth(cfdata->channel_names, cfdata->channel);
if (channel)
{
eina_stringshare_del(conf->channel_name);
conf->channel_name = eina_stringshare_ref(channel);
}
e_mixer_update(conf->instance);
return 1;
}
static void
_lock_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
E_Config_Dialog_Data *cfdata = data;
e_widget_disabled_set(cfdata->ui.general.show_locked, !cfdata->lock_sliders);
}
static void
_basic_create_general(Evas *evas, E_Config_Dialog_Data *cfdata)
{
struct mixer_config_ui_general *ui = &cfdata->ui.general;
ui->frame = e_widget_framelist_add(evas, _("General Settings"), 0);
ui->lock_sliders = e_widget_check_add(
evas, _("Lock Sliders"), &cfdata->lock_sliders);
evas_object_smart_callback_add(
ui->lock_sliders, "changed", _lock_change, cfdata);
e_widget_framelist_object_append(ui->frame, ui->lock_sliders);
ui->show_locked = e_widget_check_add(
evas, _("Show both sliders when locked"), &cfdata->show_locked);
e_widget_disabled_set(ui->show_locked, !cfdata->lock_sliders);
e_widget_framelist_object_append(ui->frame, ui->show_locked);
ui->keybindings_popup = e_widget_check_add(
evas, _("Show Popup on volume change via keybindings"), &cfdata->keybindings_popup);
e_widget_framelist_object_append(ui->frame, ui->keybindings_popup);
}
static void
_clear_channels(E_Config_Dialog_Data *cfdata)
{
Evas_Object *o;
EINA_LIST_FREE(cfdata->ui.channels.radios, o)
evas_object_del(o);
}
static void
_fill_channels(Evas *evas, E_Config_Dialog_Data *cfdata)
{
struct mixer_config_ui_channels *ui = &cfdata->ui.channels;
Evas_Object *selected;
Evas_Coord mw, mh;
const char *name;
Eina_List *l;
int i = 0;
ui->radio = e_widget_radio_group_new(&cfdata->channel);
EINA_LIST_FOREACH(cfdata->channel_names, l, name)
{
Evas_Object *ow;
if (!name) continue;
ow = e_widget_radio_add(evas, name, i, ui->radio);
ui->radios = eina_list_append(ui->radios, ow);
e_widget_list_object_append(ui->list, ow, 1, 1, 0.0);
++i;
}
e_widget_size_min_get(ui->list, &mw, &mh);
evas_object_resize(ui->list, mw, mh);
selected = eina_list_nth(ui->radios, cfdata->channel);
if (selected)
{
Evas_Coord x, y, w, h, lx, ly;
evas_object_geometry_get(selected, &x, &y, &w, &h);
evas_object_geometry_get(ui->list, &lx, &ly, NULL, NULL);
x -= lx;
y -= ly - 10;
h += 20;
e_widget_scrollframe_child_region_show(ui->scroll, x, y, w, h);
}
}
static void
_channel_scroll_set_min_size(struct mixer_config_ui_channels *ui)
{
Evas_Coord w, h;
int len = eina_list_count(ui->radios);
if (len < 1)
return;
e_widget_size_min_get(ui->list, &w, &h);
h = 4 * h / len;
e_widget_size_min_set(ui->scroll, w, h);
}
static void
_basic_create_channels(Evas *evas, E_Config_Dialog_Data *cfdata)
{
struct mixer_config_ui_channels *ui = &cfdata->ui.channels;
ui->list = e_widget_list_add(evas, 1, 0);
ui->scroll = e_widget_scrollframe_simple_add(evas, ui->list);
ui->frame = e_widget_framelist_add(evas, _("Channels"), 0);
_fill_channels(evas, cfdata);
_channel_scroll_set_min_size(ui);
e_widget_framelist_object_append(ui->frame, ui->scroll);
}
static void
_card_change(void *data, Evas_Object *obj, void *event EINA_UNUSED)
{
E_Config_Dialog_Data *cfdata = data;
Evas *evas;
char *card;
eina_stringshare_del(cfdata->card);
e_mod_mixer_channel_names_free(cfdata->channel_names);
eina_stringshare_del(cfdata->channel_name);
card = eina_list_nth(cfdata->cards, cfdata->card_num);
cfdata->card = eina_stringshare_add(card);
_mixer_fill_channel_infos(cfdata);
evas = evas_object_evas_get(obj);
_clear_channels(cfdata);
_fill_channels(evas, cfdata);
}
static void
_basic_create_cards(Evas *evas, E_Config_Dialog_Data *cfdata)
{
struct mixer_config_ui_cards *ui = &cfdata->ui.cards;
const char *card;
Eina_List *l;
int i = 0;
ui->frame = e_widget_framelist_add(evas, _("Sound Cards"), 0);
ui->radio = e_widget_radio_group_new(&cfdata->card_num);
EINA_LIST_FOREACH(cfdata->card_names, l, card)
{
Evas_Object *ow;
if (!card) continue;
ow = e_widget_radio_add(evas, card, i, ui->radio);
e_widget_framelist_object_append(ui->frame, ow);
evas_object_smart_callback_add(ow, "changed", _card_change, cfdata);
++i;
}
}
static Evas_Object *
_basic_create(E_Config_Dialog *cfd EINA_UNUSED, Evas *evas, E_Config_Dialog_Data *cfdata)
{
if (!cfdata) return NULL;
e_dialog_resizable_set(cfd->dia, 1);
cfdata->ui.table = e_widget_table_add(e_win_evas_win_get(evas), 0);
_basic_create_general(evas, cfdata);
_basic_create_cards(evas, cfdata);
_basic_create_channels(evas, cfdata);
e_widget_table_object_append(cfdata->ui.table, cfdata->ui.general.frame,
0, 0, 1, 1, 1, 1, 1, 0);
e_widget_table_object_append(cfdata->ui.table, cfdata->ui.cards.frame,
0, 1, 1, 1, 1, 1, 1, 0);
e_widget_table_object_append(cfdata->ui.table, cfdata->ui.channels.frame,
0, 2, 1, 1, 1, 1, 1, 1);
return cfdata->ui.table;
}
void
e_mixer_config_pulse_toggle(void)
{
}
E_Config_Dialog *
e_mixer_config_dialog_new(Evas_Object *parent EINA_UNUSED, E_Mixer_Gadget_Config *conf)
{
E_Config_Dialog *dialog;
E_Config_Dialog_View *view;
if (e_config_dialog_find(_e_mixer_Name, "e_mixer_config_dialog_new"))
return NULL;
view = E_NEW(E_Config_Dialog_View, 1);
if (!view)
return NULL;
view->create_cfdata = _create_data;
view->free_cfdata = _free_data;
view->basic.create_widgets = _basic_create;
view->basic.apply_cfdata = _basic_apply;
dialog = e_config_dialog_new(NULL, _("Mixer Settings"),
_e_mixer_Name, "e_mixer_config_dialog_new",
e_mixer_theme_path(), 0, view, conf);
return dialog;
}

View File

@ -1,237 +0,0 @@
#include "e_mod_main.h"
extern const char _e_mixer_Name[];
struct _E_Config_Dialog_Data
{
int default_instance;
struct mixer_config_ui
{
Evas_Object *list;
struct mixer_config_ui_general
{
Evas_Object *frame;
E_Radio_Group *radio;
} general;
} ui;
};
static int
_find_default_instance_index(E_Mixer_Module_Context *ctxt)
{
Eina_List *l;
int i;
for (i = 0, l = ctxt->instances; l; l = l->next, i++)
if (l->data == ctxt->default_instance)
return i;
return 0;
}
static void *
_create_data(E_Config_Dialog *dialog)
{
E_Config_Dialog_Data *cfdata;
E_Mixer_Module_Context *ctxt;
cfdata = E_NEW(E_Config_Dialog_Data, 1);
if (!cfdata)
return NULL;
ctxt = dialog->data;
cfdata->default_instance = _find_default_instance_index(ctxt);
return cfdata;
}
static void
_free_data(E_Config_Dialog *dialog, E_Config_Dialog_Data *cfdata)
{
E_Mixer_Module_Context *ctxt = dialog->data;
if (ctxt)
ctxt->conf_dialog = NULL;
E_FREE(cfdata);
}
static int
_basic_apply(E_Config_Dialog *dialog, E_Config_Dialog_Data *cfdata)
{
E_Mixer_Module_Context *ctxt = dialog->data;
ctxt->default_instance = eina_list_nth(ctxt->instances,
cfdata->default_instance);
if (ctxt->default_instance)
{
E_Mixer_Module_Config *conf;
const char *id;
conf = ctxt->conf;
if (conf->default_gc_id)
eina_stringshare_del(conf->default_gc_id);
id = ctxt->default_instance->gcc->cf->id;
conf->default_gc_id = eina_stringshare_add(id);
conf->desktop_notification = ctxt->desktop_notification;
conf->disable_pulse = ctxt->disable_pulse;
if ((ctxt->external_mixer_enabled) &&
(!strlen(ctxt->external_mixer_command)))
return 0;
conf->external_mixer_enabled = ctxt->external_mixer_enabled;
if (conf->external_mixer_command)
eina_stringshare_del(conf->external_mixer_command);
if (ctxt->external_mixer_enabled)
conf->external_mixer_command = eina_stringshare_add(ctxt->external_mixer_command);
}
return 1;
}
static void
_basic_create_general(E_Config_Dialog *dialog, Evas *evas, E_Config_Dialog_Data *cfdata)
{
struct mixer_config_ui_general *ui = &cfdata->ui.general;
E_Mixer_Module_Context *ctxt = dialog->data;
Evas_Object *label, *chk, *edit;
Eina_List *l;
int i;
ui->frame = e_widget_framelist_add(evas, _("General Settings"), 0);
label = e_widget_label_add(evas, _("Mixer to use for global actions:"));
e_widget_framelist_object_append(ui->frame, label);
ui->radio = e_widget_radio_group_new(&cfdata->default_instance);
for (i = 0, l = ctxt->instances; l; l = l->next, i++)
{
E_Mixer_Instance *inst;
E_Mixer_Gadget_Config *conf;
Evas_Object *o;
char name[128];
const char *card_name;
inst = l->data;
conf = inst->conf;
card_name = e_mixer_system_get_card_name(conf->card);
snprintf(name, sizeof(name), "%s: %s", card_name, conf->channel_name);
eina_stringshare_del(card_name);
o = e_widget_radio_add(evas, name, i, ui->radio);
e_widget_framelist_object_append(ui->frame, o);
}
e_widget_list_object_append(cfdata->ui.list, ui->frame, 1, 1, 0.5);
chk = e_widget_check_add(evas, _("Display desktop notifications on volume change"), &ctxt->desktop_notification);
e_widget_check_checked_set(chk, ctxt->desktop_notification);
#ifndef HAVE_ENOTIFY
e_widget_disabled_set(chk, EINA_TRUE);
#endif
e_widget_list_object_append(cfdata->ui.list, chk, 1, 1, 0.5);
chk = e_widget_check_add(evas, _("Disable PulseAudio"), &ctxt->disable_pulse);
e_widget_check_checked_set(chk, ctxt->disable_pulse);
e_widget_list_object_append(cfdata->ui.list, chk, 1, 1, 0.5);
chk = e_widget_check_add(evas, _("Enable external Mixer Command"), &ctxt->external_mixer_enabled);
e_widget_check_checked_set(chk, ctxt->external_mixer_enabled);
e_widget_list_object_append(cfdata->ui.list, chk, 1, 1, 0.5);
edit = e_widget_entry_add(dialog->dia->win, &ctxt->external_mixer_command, NULL, NULL, NULL);
e_widget_list_object_append(cfdata->ui.list, edit, 1, 1, 0.5);
}
static void
cb_mixer_app_del(E_Dialog *dialog EINA_UNUSED, void *data)
{
E_Mixer_Module_Context *ctxt = data;
ctxt->mixer_dialog = NULL;
}
static void
cb_mixer_call(void *data, void *data2 EINA_UNUSED)
{
Eina_List *l;
E_Mixer_Module_Context *ctxt = data;
if (ctxt->mixer_dialog)
{
e_dialog_show(ctxt->mixer_dialog);
return;
}
if (ctxt->conf->external_mixer_enabled)
{
E_Zone *zone = e_zone_current_get();
e_exec (zone, NULL, ctxt->conf->external_mixer_command, NULL, NULL);
return;
}
ctxt->mixer_dialog = e_mixer_app_dialog_new(NULL, cb_mixer_app_del, ctxt);
for (l = ctxt->instances; l; l = l->next)
{
E_Mixer_Instance *inst;
E_Mixer_Gadget_Config *conf;
inst = l->data;
conf = inst->conf;
if (conf)
{
e_mixer_app_dialog_select(ctxt->mixer_dialog, conf->card, conf->channel_name);
break;
}
}
}
static void
_basic_create_mixer_call(E_Config_Dialog *dialog, Evas *evas, E_Config_Dialog_Data *cfdata)
{
Evas_Object *button;
button = e_widget_button_add(evas, _("Launch mixer..."), NULL,
cb_mixer_call, dialog->data, NULL);
e_widget_list_object_append(cfdata->ui.list, button, 0, 0, 0.0);
}
static Evas_Object *
_basic_create(E_Config_Dialog *dialog, Evas *evas, E_Config_Dialog_Data *cfdata)
{
if (!cfdata)
return NULL;
cfdata->ui.list = e_widget_list_add(evas, 0, 0);
_basic_create_general(dialog, evas, cfdata);
_basic_create_mixer_call(dialog, evas, cfdata);
return cfdata->ui.list;
}
E_Config_Dialog *
e_mixer_config_module_dialog_new(Evas_Object *parent EINA_UNUSED, E_Mixer_Module_Context *ctxt)
{
E_Config_Dialog *dialog;
E_Config_Dialog_View *view;
if (e_config_dialog_find(_e_mixer_Name, "extensions/mixer"))
return NULL;
view = E_NEW(E_Config_Dialog_View, 1);
if (!view)
return NULL;
view->create_cfdata = _create_data;
view->free_cfdata = _free_data;
view->basic.create_widgets = _basic_create;
view->basic.apply_cfdata = _basic_apply;
dialog = e_config_dialog_new(NULL, _("Mixer Module Settings"),
_e_mixer_Name, "extensions/mixer",
e_mixer_theme_path(), 0, view, ctxt);
return dialog;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,103 +0,0 @@
#ifndef E_MOD_MAIN_H
#define E_MOD_MAIN_H
#include "e.h"
#include "e_mod_mixer.h"
/* Increment for Major Changes */
#define MOD_CONFIG_FILE_EPOCH 1
/* Increment for Minor Changes (ie: user doesn't need a new config) */
#define MOD_CONFIG_FILE_GENERATION 1
#define MOD_CONFIG_FILE_VERSION ((MOD_CONFIG_FILE_EPOCH * 1000000) + MOD_CONFIG_FILE_GENERATION)
typedef struct E_Mixer_Gadget_Config
{
int lock_sliders;
int show_locked;
int keybindings_popup;
const char *card;
const char *channel_name;
const char *id;
E_Mixer_Channel_State state;
Eina_Bool using_default;
E_Config_Dialog *dialog;
struct E_Mixer_Instance *instance;
} E_Mixer_Gadget_Config;
typedef struct E_Mixer_Module_Config
{
int version;
const char *default_gc_id;
Eina_Hash *gadgets;
int desktop_notification;
int disable_pulse;
int external_mixer_enabled;
const char *external_mixer_command;
} E_Mixer_Module_Config;
typedef struct E_Mixer_Instance
{
E_Gadcon_Client *gcc;
E_Gadcon_Popup *popup;
Ecore_Timer *popup_timer;
struct
{
Evas_Object *gadget;
Evas_Object *label;
Evas_Object *left;
Evas_Object *right;
Evas_Object *mute;
Evas_Object *table;
Evas_Object *button;
} ui;
E_Mixer_System *sys;
E_Mixer_Channel_Info *channel;
E_Mixer_Channel_State mixer_state;
E_Mixer_Gadget_Config *conf;
#ifdef HAVE_ENOTIFY
unsigned int notification_id;
#endif
} E_Mixer_Instance;
typedef struct E_Mixer_Module_Context
{
E_Config_DD *module_conf_edd;
E_Config_DD *gadget_conf_edd;
E_Mixer_Module_Config *conf;
E_Config_Dialog *conf_dialog;
E_Mixer_Instance *default_instance;
Eina_List *instances;
E_Dialog *mixer_dialog;
double last_act_time;
struct st_mixer_actions
{
E_Action *incr;
E_Action *decr;
E_Action *mute;
} actions;
int desktop_notification;
int disable_pulse;
int external_mixer_enabled;
char *external_mixer_command;
} E_Mixer_Module_Context;
E_API extern E_Module_Api e_modapi;
E_API void *e_modapi_init(E_Module *m);
E_API int e_modapi_shutdown(E_Module *m);
E_API int e_modapi_save(E_Module *m);
E_Config_Dialog *e_mixer_config_module_dialog_new(Evas_Object *parent, E_Mixer_Module_Context *ctxt);
E_Config_Dialog *e_mixer_config_dialog_new(Evas_Object *parent, E_Mixer_Gadget_Config *conf);
E_Dialog *e_mixer_app_dialog_new(Evas_Object *parent, void (*func)(E_Dialog *dialog, void *data), void *data);
int e_mixer_app_dialog_select(E_Dialog *dialog, const char *card_name, const char *channel_name);
int e_mixer_update(E_Mixer_Instance *inst);
const char *e_mixer_theme_path(void);
void e_mod_mixer_pulse_ready(Eina_Bool);
void e_mod_mixer_pulse_update(void);
#endif

View File

@ -1,114 +0,0 @@
#include "e_mod_mixer.h"
Eina_Bool _mixer_using_default = EINA_FALSE;
E_Mixer_Volume_Get_Cb e_mod_mixer_volume_get;
E_Mixer_Volume_Set_Cb e_mod_mixer_volume_set;
E_Mixer_Mute_Get_Cb e_mod_mixer_mute_get;
E_Mixer_Mute_Set_Cb e_mod_mixer_mute_set;
E_Mixer_State_Get_Cb e_mod_mixer_state_get;
E_Mixer_Cb e_mod_mixer_new;
E_Mixer_Cb e_mod_mixer_del;
E_Mixer_Cb e_mod_mixer_channel_default_name_get;
E_Mixer_Cb e_mod_mixer_channel_info_get_by_name;
E_Mixer_Cb e_mod_mixer_channels_get;
E_Mixer_Cb e_mod_mixer_channel_names_get;
E_Mixer_Cb e_mod_mixer_card_name_get;
E_Mixer_Cb e_mod_mixer_card_names_get;
E_Mixer_Cb e_mod_mixer_card_default_get;
void
e_mixer_default_setup(void)
{
e_mod_mixer_volume_get = (void *)e_mixer_system_get_volume;
e_mod_mixer_volume_set = (void *)e_mixer_system_set_volume;
e_mod_mixer_mute_get = (void *)e_mixer_system_get_mute;
e_mod_mixer_mute_set = (void *)e_mixer_system_set_mute;
e_mod_mixer_state_get = (void *)e_mixer_system_get_state;
e_mod_mixer_new = (void *)e_mixer_system_new;
e_mod_mixer_del = (void *)e_mixer_system_del;
e_mod_mixer_channel_default_name_get = (void *)e_mixer_system_get_default_channel_name;
e_mod_mixer_channel_info_get_by_name = (void *)e_mixer_system_get_channel_by_name;
e_mod_mixer_channels_get = (void *)e_mixer_system_get_channels;
e_mod_mixer_channel_names_get = (void *)e_mixer_system_get_channel_names;
e_mod_mixer_card_name_get = (void *)e_mixer_system_get_card_name;
e_mod_mixer_card_names_get = (void *)e_mixer_system_get_cards;
e_mod_mixer_card_default_get = (void *)e_mixer_system_get_default_card;
_mixer_using_default = EINA_TRUE;
}
void
e_mixer_pulse_setup()
{
e_mod_mixer_volume_get = (void *)e_mixer_pulse_get_volume;
e_mod_mixer_volume_set = (void *)e_mixer_pulse_set_volume;
e_mod_mixer_mute_get = (void *)e_mixer_pulse_get_mute;
e_mod_mixer_mute_set = (void *)e_mixer_pulse_set_mute;
e_mod_mixer_state_get = (void *)e_mixer_pulse_get_state;
e_mod_mixer_new = (void *)e_mixer_pulse_new;
e_mod_mixer_del = (void *)e_mixer_pulse_del;
e_mod_mixer_channel_default_name_get = (void *)e_mixer_pulse_get_default_channel_name;
e_mod_mixer_channel_info_get_by_name = (void *)e_mixer_pulse_get_channel_by_name;
e_mod_mixer_channels_get = (void *)e_mixer_pulse_get_channels;
e_mod_mixer_channel_names_get = (void *)e_mixer_pulse_get_channel_names;
e_mod_mixer_card_name_get = (void *)e_mixer_pulse_get_card_name;
e_mod_mixer_card_names_get = (void *)e_mixer_pulse_get_cards;
e_mod_mixer_card_default_get = (void *)e_mixer_pulse_get_default_card;
_mixer_using_default = EINA_FALSE;
}
static int
_channel_info_cmp(const void *data_a, const void *data_b)
{
const E_Mixer_Channel_Info *a = data_a, *b = data_b;
if (e_mod_mixer_channel_group_get(a) == e_mod_mixer_channel_group_get(b))
return strcmp(a->name, b->name);
if (e_mod_mixer_channel_is_boost(a))
return 1;
if (e_mod_mixer_channel_is_boost(b))
return -1;
if (e_mod_mixer_channel_group_get(a) < e_mod_mixer_channel_group_get(b))