forked from enlightenment/enlightenment
mixer: Add cards settings into pulseaudio backend
Summary: This commit bring the support to set a profile on audio hardware via pulseaudio. You are now able to configure the output of your audio hardware via emixer without the help of pavucontrol. @fix T3127 Reviewers: zmike!, devilhorns Subscribers: cedric Tags: #enlightenment-git Maniphest Tasks: T3127 Differential Revision: https://phab.enlightenment.org/D7569
This commit is contained in:
parent
a0611d0026
commit
1527599b78
|
@ -2,10 +2,10 @@
|
|||
#include "emix.h"
|
||||
|
||||
Evas_Object *win;
|
||||
Evas_Object *source_scroller, *sink_input_scroller, *sink_scroller;
|
||||
Evas_Object *source_box, *sink_input_box, *sink_box;
|
||||
Evas_Object *source_scroller, *sink_input_scroller, *sink_scroller, *card_scroller;
|
||||
Evas_Object *source_box, *sink_input_box, *sink_box, *card_box;
|
||||
|
||||
Eina_List *source_list = NULL, *sink_input_list = NULL, *sink_list = NULL;
|
||||
Eina_List *source_list = NULL, *sink_input_list = NULL, *sink_list = NULL, *card_list = NULL;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -514,6 +514,117 @@ _emix_source_change(Emix_Source *source)
|
|||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
static void
|
||||
_cb_card_profile_change(void *data,
|
||||
Evas_Object *obj,
|
||||
void *event_info EINA_UNUSED)
|
||||
{
|
||||
Emix_Profile *profile = data;
|
||||
Evas_Object *bxv = evas_object_data_get(obj, "parent");
|
||||
Emix_Card *card = evas_object_data_get(bxv, "card");
|
||||
elm_object_text_set(obj, profile->description);
|
||||
emix_card_profile_set(card, profile);
|
||||
}
|
||||
|
||||
static void
|
||||
_emix_card_add(Emix_Card *card)
|
||||
{
|
||||
Evas_Object *bxv, *bx, *lb, *hv, *sep;
|
||||
Eina_List *l;
|
||||
Emix_Profile *profile;
|
||||
|
||||
bxv = elm_box_add(win);
|
||||
card_list = eina_list_append(card_list, bxv);
|
||||
evas_object_data_set(bxv, "card", card);
|
||||
evas_object_size_hint_weight_set(bxv, EVAS_HINT_EXPAND, 0.0);
|
||||
evas_object_size_hint_align_set(bxv, EVAS_HINT_FILL, 0.0);
|
||||
|
||||
bx = elm_box_add(win);
|
||||
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(bxv, bx);
|
||||
evas_object_show(bx);
|
||||
|
||||
lb = elm_label_add(win);
|
||||
elm_object_text_set(lb, card->name);
|
||||
evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.5);
|
||||
evas_object_size_hint_align_set(lb, 0.0, 0.5);
|
||||
elm_box_pack_end(bx, lb);
|
||||
evas_object_show(lb);
|
||||
|
||||
hv = elm_hoversel_add(win);
|
||||
evas_object_data_set(hv, "parent", bxv);
|
||||
evas_object_data_set(bxv, "profile", hv);
|
||||
elm_hoversel_hover_parent_set(hv, win);
|
||||
EINA_LIST_FOREACH(card->profiles, l, profile)
|
||||
{
|
||||
if (!profile->plugged) continue;
|
||||
elm_hoversel_item_add(hv, profile->description,
|
||||
NULL, ELM_ICON_NONE,
|
||||
_cb_card_profile_change, profile);
|
||||
if (profile->active) elm_object_text_set(hv, profile->description);
|
||||
}
|
||||
evas_object_size_hint_weight_set(hv, 0.0, 0.5);
|
||||
evas_object_size_hint_align_set(hv, EVAS_HINT_FILL, 0.5);
|
||||
elm_box_pack_end(bx, hv);
|
||||
evas_object_show(hv);
|
||||
|
||||
sep = elm_separator_add(win);
|
||||
elm_separator_horizontal_set(sep, EINA_TRUE);
|
||||
evas_object_size_hint_weight_set(sep, EVAS_HINT_EXPAND, 0.0);
|
||||
evas_object_size_hint_align_set(sep, EVAS_HINT_FILL, 0.0);
|
||||
elm_box_pack_end(bxv, sep);
|
||||
evas_object_show(sep);
|
||||
|
||||
elm_box_pack_end(card_box, bxv);
|
||||
evas_object_show(bxv);
|
||||
}
|
||||
|
||||
static void
|
||||
_emix_card_change(Emix_Card *card)
|
||||
{
|
||||
const Eina_List *l;
|
||||
Evas_Object *bxv, *hv;
|
||||
Emix_Profile *profile;
|
||||
|
||||
EINA_LIST_FOREACH(card_list, l, bxv)
|
||||
{
|
||||
if (evas_object_data_get(bxv, "card") == card) break;
|
||||
}
|
||||
if (!l) return;
|
||||
hv = evas_object_data_get(bxv, "profile");
|
||||
elm_hoversel_clear(hv);
|
||||
EINA_LIST_FOREACH(card->profiles, l, profile)
|
||||
{
|
||||
if (!profile->plugged) continue;
|
||||
elm_hoversel_item_add(hv, profile->description,
|
||||
NULL, ELM_ICON_NONE,
|
||||
_cb_card_profile_change, profile);
|
||||
if (profile->active) elm_object_text_set(hv, profile->description);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_emix_card_del(Emix_Card *card)
|
||||
{
|
||||
Eina_List *l;
|
||||
Evas_Object *bxv;
|
||||
EINA_LIST_FOREACH(card_list, l, bxv)
|
||||
{
|
||||
if (evas_object_data_get(bxv, "card") == card)
|
||||
{
|
||||
card_list = eina_list_remove_list(card_list, l);
|
||||
evas_object_del(bxv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static void
|
||||
_cb_emix_event(void *data EINA_UNUSED, enum Emix_Event event, void *event_info)
|
||||
|
@ -552,6 +663,15 @@ _cb_emix_event(void *data EINA_UNUSED, enum Emix_Event event, void *event_info)
|
|||
case EMIX_SOURCE_CHANGED_EVENT:
|
||||
_emix_source_change(event_info);
|
||||
break;
|
||||
case EMIX_CARD_ADDED_EVENT:
|
||||
_emix_card_add(event_info);
|
||||
break;
|
||||
case EMIX_CARD_REMOVED_EVENT:
|
||||
_emix_card_del(event_info);
|
||||
break;
|
||||
case EMIX_CARD_CHANGED_EVENT:
|
||||
_emix_card_change(event_info);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -567,6 +687,7 @@ _cb_playback(void *data EINA_UNUSED,
|
|||
evas_object_hide(source_scroller);
|
||||
evas_object_show(sink_input_scroller);
|
||||
evas_object_hide(sink_scroller);
|
||||
evas_object_hide(card_scroller);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -577,6 +698,7 @@ _cb_outputs(void *data EINA_UNUSED,
|
|||
evas_object_hide(source_scroller);
|
||||
evas_object_hide(sink_input_scroller);
|
||||
evas_object_show(sink_scroller);
|
||||
evas_object_hide(card_scroller);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -587,8 +709,21 @@ _cb_inputs(void *data EINA_UNUSED,
|
|||
evas_object_show(source_scroller);
|
||||
evas_object_hide(sink_input_scroller);
|
||||
evas_object_hide(sink_scroller);
|
||||
evas_object_hide(card_scroller);
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_card(void *data EINA_UNUSED,
|
||||
Evas_Object *obj EINA_UNUSED,
|
||||
void *event_info EINA_UNUSED)
|
||||
{
|
||||
evas_object_hide(source_scroller);
|
||||
evas_object_hide(sink_input_scroller);
|
||||
evas_object_hide(sink_scroller);
|
||||
evas_object_show(card_scroller);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void
|
||||
|
@ -633,6 +768,18 @@ _fill_sink(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_fill_card(void)
|
||||
{
|
||||
const Eina_List *l;
|
||||
Emix_Card *card;
|
||||
|
||||
EINA_LIST_FOREACH(emix_cards_get(), l, card)
|
||||
{
|
||||
_emix_card_add(card);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EAPI_MAIN int
|
||||
|
@ -674,6 +821,7 @@ elm_main(int argc, char **argv)
|
|||
elm_toolbar_item_append(tbar, NULL, "Playback", _cb_playback, NULL);
|
||||
elm_toolbar_item_append(tbar, NULL, "Outputs", _cb_outputs, NULL);
|
||||
elm_toolbar_item_append(tbar, NULL, "Inputs", _cb_inputs, NULL);
|
||||
elm_toolbar_item_append(tbar, NULL, "Cards", _cb_card, NULL);
|
||||
|
||||
elm_table_pack(tb, tbar, 0, 0, 1, 1);
|
||||
evas_object_show(tbar);
|
||||
|
@ -697,6 +845,12 @@ elm_main(int argc, char **argv)
|
|||
evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
elm_table_pack(tb, sc, 0, 1, 1, 1);
|
||||
|
||||
sc = elm_scroller_add(win);
|
||||
card_scroller = sc;
|
||||
evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
||||
evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
elm_table_pack(tb, sc, 0, 1, 1, 1);
|
||||
|
||||
bx = elm_box_add(win);
|
||||
source_box = bx;
|
||||
evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
|
||||
|
@ -718,6 +872,13 @@ elm_main(int argc, char **argv)
|
|||
elm_object_content_set(sink_scroller, bx);
|
||||
evas_object_show(bx);
|
||||
|
||||
bx = elm_box_add(win);
|
||||
card_box = bx;
|
||||
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_object_content_set(card_scroller, bx);
|
||||
evas_object_show(bx);
|
||||
|
||||
rect = evas_object_rectangle_add(evas_object_evas_get(win));
|
||||
evas_object_size_hint_weight_set(rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
||||
evas_object_size_hint_align_set(rect, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
|
@ -729,6 +890,7 @@ elm_main(int argc, char **argv)
|
|||
_fill_source();
|
||||
_fill_sink_input();
|
||||
_fill_sink();
|
||||
_fill_card();
|
||||
evas_object_show(win);
|
||||
|
||||
elm_run();
|
||||
|
|
|
@ -532,7 +532,9 @@ _alsa_backend =
|
|||
_alsa_sources_get,/*source*/
|
||||
_alsa_sources_mute_set,/* source mute set */
|
||||
_alsa_sources_volume_set, /* source volume set */
|
||||
NULL /* advanced options */
|
||||
NULL, /* advanced options */
|
||||
NULL, /* card list */
|
||||
NULL /* card profile set */
|
||||
};
|
||||
|
||||
E_API Emix_Backend *
|
||||
|
|
|
@ -27,7 +27,7 @@ typedef struct _Context
|
|||
Ecore_Timer *connect;
|
||||
int default_sink;
|
||||
|
||||
Eina_List *sinks, *sources, *inputs;
|
||||
Eina_List *sinks, *sources, *inputs, *cards;
|
||||
Eina_Bool connected;
|
||||
} Context;
|
||||
|
||||
|
@ -50,6 +50,18 @@ typedef struct _Source
|
|||
int idx;
|
||||
} Source;
|
||||
|
||||
typedef struct _Profile
|
||||
{
|
||||
Emix_Profile base;
|
||||
uint32_t priority;
|
||||
} Profile;
|
||||
|
||||
typedef struct _Card
|
||||
{
|
||||
Emix_Card base;
|
||||
int idx;
|
||||
} Card;
|
||||
|
||||
static Context *ctx = NULL;
|
||||
extern pa_mainloop_api functable;
|
||||
|
||||
|
@ -122,6 +134,22 @@ _source_del(Source *source)
|
|||
free(source);
|
||||
}
|
||||
|
||||
static void
|
||||
_card_del(Card *card)
|
||||
{
|
||||
Profile *profile;
|
||||
EINA_SAFETY_ON_NULL_RETURN(card);
|
||||
|
||||
EINA_LIST_FREE(card->base.profiles, profile)
|
||||
{
|
||||
eina_stringshare_del(profile->base.name);
|
||||
eina_stringshare_del(profile->base.description);
|
||||
free(profile);
|
||||
}
|
||||
eina_stringshare_del(card->base.name);
|
||||
free(card);
|
||||
}
|
||||
|
||||
static void
|
||||
_sink_cb(pa_context *c EINA_UNUSED, const pa_sink_info *info, int eol,
|
||||
void *userdata EINA_UNUSED)
|
||||
|
@ -600,6 +628,179 @@ _server_info_cb(pa_context *c, const pa_server_info *info,
|
|||
pa_operation_unref(o);
|
||||
}
|
||||
|
||||
static int
|
||||
_profile_sort_cb(const Profile *p1, const Profile *p2)
|
||||
{
|
||||
if (p1->priority < p2->priority) return 1;
|
||||
if (p1->priority > p2->priority) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_card_cb(pa_context *c, const pa_card_info *info, int eol, void *userdata EINA_UNUSED)
|
||||
{
|
||||
Card *card;
|
||||
const char *description;
|
||||
uint32_t i, j;
|
||||
Profile *profile;
|
||||
|
||||
if (eol < 0) {
|
||||
if (pa_context_errno(c) == PA_ERR_NOENTITY)
|
||||
return;
|
||||
|
||||
ERR("Card callback failure: %d", pa_context_errno(c));
|
||||
return;
|
||||
}
|
||||
if (eol > 0)
|
||||
return;
|
||||
|
||||
card = calloc(1, sizeof(Card));
|
||||
EINA_SAFETY_ON_NULL_RETURN(card);
|
||||
|
||||
card->idx = info->index;
|
||||
|
||||
description = pa_proplist_gets(info->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
card->base.name = description
|
||||
? eina_stringshare_add(description)
|
||||
: eina_stringshare_add(info->name);
|
||||
|
||||
for (i = 0; i < info->n_ports; ++i)
|
||||
{
|
||||
for (j = 0; j < info->ports[i]->n_profiles; ++j)
|
||||
{
|
||||
profile = calloc(1, sizeof(Profile));
|
||||
profile->base.name = eina_stringshare_add(info->ports[i]->profiles[j]->name);
|
||||
profile->base.description = eina_stringshare_add(info->ports[i]->profiles[j]->description);
|
||||
profile->priority = info->ports[i]->profiles[j]->priority;
|
||||
if ((info->ports[i]->available == PA_PORT_AVAILABLE_NO)
|
||||
&& ((strcmp("analog-output-speaker", profile->base.name))
|
||||
|| (strcmp("analog-input-microphone-internal", profile->base.name))))
|
||||
profile->base.plugged = EINA_FALSE;
|
||||
else
|
||||
profile->base.plugged = EINA_TRUE;
|
||||
|
||||
if (info->active_profile)
|
||||
{
|
||||
if (info->ports[i]->profiles[j]->name == info->active_profile->name)
|
||||
profile->base.active = EINA_TRUE;
|
||||
}
|
||||
card->base.profiles =
|
||||
eina_list_sorted_insert(card->base.profiles,
|
||||
(Eina_Compare_Cb)_profile_sort_cb,
|
||||
profile);
|
||||
}
|
||||
}
|
||||
ctx->cards = eina_list_append(ctx->cards, card);
|
||||
if (ctx->cb)
|
||||
ctx->cb((void *)ctx->userdata, EMIX_CARD_ADDED_EVENT,
|
||||
(Emix_Card *)card);
|
||||
}
|
||||
|
||||
static void
|
||||
_card_changed_cb(pa_context *c EINA_UNUSED, const pa_card_info *info, int eol,
|
||||
void *userdata EINA_UNUSED)
|
||||
{
|
||||
Card *card = NULL, *ca;
|
||||
Eina_List *l;
|
||||
const char *description;
|
||||
uint32_t i, j;
|
||||
Profile *profile;
|
||||
|
||||
if (eol < 0)
|
||||
{
|
||||
if (pa_context_errno(c) == PA_ERR_NOENTITY)
|
||||
return;
|
||||
|
||||
ERR("Card callback failure");
|
||||
return;
|
||||
}
|
||||
|
||||
if (eol > 0)
|
||||
return;
|
||||
|
||||
DBG("card index: %d\n", info->index);
|
||||
|
||||
EINA_LIST_FOREACH(ctx->cards, l, ca)
|
||||
{
|
||||
if (ca->idx == (int)info->index)
|
||||
{
|
||||
card = ca;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(card);
|
||||
|
||||
description = pa_proplist_gets(info->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
eina_stringshare_replace(&card->base.name,
|
||||
(description
|
||||
? eina_stringshare_add(description)
|
||||
: eina_stringshare_add(info->name)));
|
||||
|
||||
EINA_LIST_FREE(card->base.profiles, profile)
|
||||
{
|
||||
eina_stringshare_del(profile->base.name);
|
||||
eina_stringshare_del(profile->base.description);
|
||||
free(profile);
|
||||
}
|
||||
for (i = 0; i < info->n_ports; ++i)
|
||||
{
|
||||
for (j = 0; j < info->ports[i]->n_profiles; ++j)
|
||||
{
|
||||
profile = calloc(1, sizeof(Profile));
|
||||
profile->base.name = eina_stringshare_add(info->ports[i]->profiles[j]->name);
|
||||
profile->base.description = eina_stringshare_add(info->ports[i]->profiles[j]->description);
|
||||
profile->priority = info->ports[i]->profiles[j]->priority;
|
||||
if ((info->ports[i]->available == PA_PORT_AVAILABLE_NO)
|
||||
&& ((strcmp("analog-output-speaker", profile->base.name))
|
||||
|| (strcmp("analog-input-microphone-internal", profile->base.name))))
|
||||
profile->base.plugged = EINA_FALSE;
|
||||
else
|
||||
profile->base.plugged = EINA_TRUE;
|
||||
|
||||
if (info->active_profile)
|
||||
{
|
||||
if (info->ports[i]->profiles[j]->name == info->active_profile->name)
|
||||
profile->base.active = EINA_TRUE;
|
||||
}
|
||||
card->base.profiles =
|
||||
eina_list_sorted_insert(card->base.profiles,
|
||||
(Eina_Compare_Cb)_profile_sort_cb,
|
||||
profile);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->cb)
|
||||
ctx->cb((void *)ctx->userdata, EMIX_CARD_CHANGED_EVENT,
|
||||
(Emix_Card *)card);
|
||||
}
|
||||
|
||||
static void
|
||||
_card_remove_cb(int index, void *data EINA_UNUSED)
|
||||
{
|
||||
Card *card;
|
||||
Eina_List *l;
|
||||
EINA_SAFETY_ON_NULL_RETURN(ctx);
|
||||
|
||||
DBG("Removing card: %d", index);
|
||||
|
||||
EINA_LIST_FOREACH(ctx->cards, l, card)
|
||||
{
|
||||
if (card->idx == index)
|
||||
{
|
||||
ctx->cards = eina_list_remove_list(ctx->cards, l);
|
||||
if (ctx->cb)
|
||||
ctx->cb((void *)ctx->userdata,
|
||||
EMIX_CARD_REMOVED_EVENT,
|
||||
(Emix_Card *)card);
|
||||
_card_del(card);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_subscribe_cb(pa_context *c, pa_subscription_event_type_t t,
|
||||
uint32_t index, void *data)
|
||||
|
@ -699,6 +900,34 @@ _subscribe_cb(pa_context *c, pa_subscription_event_type_t t,
|
|||
}
|
||||
pa_operation_unref(o);
|
||||
break;
|
||||
|
||||
case PA_SUBSCRIPTION_EVENT_CARD:
|
||||
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
|
||||
PA_SUBSCRIPTION_EVENT_REMOVE)
|
||||
_card_remove_cb(index, data);
|
||||
else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
|
||||
PA_SUBSCRIPTION_EVENT_NEW)
|
||||
{
|
||||
if (!(o = pa_context_get_card_info_by_index(c, index, _card_cb,
|
||||
data)))
|
||||
{
|
||||
ERR("pa_context_get_card_info() failed");
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(o = pa_context_get_card_info_by_index(c, index, _card_changed_cb,
|
||||
data)))
|
||||
{
|
||||
ERR("pa_context_get_card_info() failed");
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
WRN("Event not handled");
|
||||
break;
|
||||
|
@ -771,6 +1000,17 @@ _pulse_pa_state_cb(pa_context *context, void *data)
|
|||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
||||
if (!(o = pa_context_get_card_info_list(context, _card_cb,
|
||||
ctx)))
|
||||
{
|
||||
ERR("pa_context_get_server_info() failed");
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case PA_CONTEXT_FAILED:
|
||||
|
@ -908,6 +1148,7 @@ _disconnect_cb()
|
|||
Source *source;
|
||||
Sink *sink;
|
||||
Sink_Input *input;
|
||||
Card *card;
|
||||
|
||||
if (ctx->cb)
|
||||
ctx->cb((void *)ctx->userdata, EMIX_DISCONNECTED_EVENT, NULL);
|
||||
|
@ -918,6 +1159,8 @@ _disconnect_cb()
|
|||
_sink_del(sink);
|
||||
EINA_LIST_FREE(ctx->inputs, input)
|
||||
_sink_input_del(input);
|
||||
EINA_LIST_FREE(ctx->cards, card)
|
||||
_card_del(card);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1087,6 +1330,34 @@ _max_volume(void)
|
|||
return 150;
|
||||
}
|
||||
|
||||
static const Eina_List *
|
||||
_cards_get(void)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
|
||||
return ctx->cards;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_card_profile_set(Emix_Card *card, const Emix_Profile *profile)
|
||||
{
|
||||
pa_operation* o;
|
||||
Card *c = (Card *)card;
|
||||
Profile *p = (Profile *)profile;
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(ctx && ctx->context &&
|
||||
(c != NULL) && (p != NULL), EINA_FALSE);
|
||||
|
||||
if (!(o = pa_context_set_card_profile_by_index(ctx->context,
|
||||
c->idx, p->base.name, NULL,
|
||||
NULL)))
|
||||
{
|
||||
ERR("pa_context_set_card_profile_by_index() failed");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Emix_Backend
|
||||
_pulseaudio_backend =
|
||||
{
|
||||
|
@ -1109,6 +1380,8 @@ _pulseaudio_backend =
|
|||
_source_mute_set,
|
||||
_source_volume_set,
|
||||
NULL,
|
||||
_cards_get,
|
||||
_card_profile_set
|
||||
};
|
||||
|
||||
E_API Emix_Backend *
|
||||
|
|
|
@ -33,6 +33,7 @@ typedef struct Context
|
|||
Eina_Array *backends;
|
||||
Eina_List *backends_names;
|
||||
Eina_List *callbacks;
|
||||
Eina_List *configs;
|
||||
|
||||
Emix_Backend *loaded;
|
||||
} Context;
|
||||
|
@ -170,6 +171,13 @@ emix_backends_available(void)
|
|||
return ctx->backends_names;
|
||||
}
|
||||
|
||||
const Eina_List *
|
||||
emix_configs_available(void)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
|
||||
return ctx->configs;
|
||||
}
|
||||
|
||||
int
|
||||
emix_max_volume_get(void)
|
||||
{
|
||||
|
@ -402,3 +410,24 @@ emix_event_callback_del(Emix_Event_Cb cb)
|
|||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
const Eina_List*
|
||||
emix_cards_get(void)
|
||||
{
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->loaded &&
|
||||
ctx->loaded->ebackend_cards_get), NULL);
|
||||
|
||||
return ctx->loaded->ebackend_cards_get();
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
emix_card_profile_set(Emix_Card *card, Emix_Profile *profile)
|
||||
{
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->loaded &&
|
||||
ctx->loaded->ebackend_card_profile_set &&
|
||||
card && profile), EINA_FALSE);
|
||||
|
||||
return ctx->loaded->ebackend_card_profile_set(card, profile);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -36,7 +36,10 @@ enum Emix_Event {
|
|||
EMIX_SINK_INPUT_CHANGED_EVENT,
|
||||
EMIX_SOURCE_ADDED_EVENT,
|
||||
EMIX_SOURCE_REMOVED_EVENT,
|
||||
EMIX_SOURCE_CHANGED_EVENT
|
||||
EMIX_SOURCE_CHANGED_EVENT,
|
||||
EMIX_CARD_ADDED_EVENT,
|
||||
EMIX_CARD_REMOVED_EVENT,
|
||||
EMIX_CARD_CHANGED_EVENT
|
||||
};
|
||||
|
||||
typedef struct _Emix_Volume {
|
||||
|
@ -73,6 +76,18 @@ typedef struct _Emix_Source {
|
|||
Eina_Bool mute;
|
||||
} Emix_Source;
|
||||
|
||||
typedef struct _Emix_Profile {
|
||||
const char *name;
|
||||
const char *description;
|
||||
Eina_Bool plugged;
|
||||
Eina_Bool active;
|
||||
} Emix_Profile;
|
||||
|
||||
typedef struct _Emix_Card {
|
||||
const char *name;
|
||||
Eina_List *profiles;
|
||||
} Emix_Card;
|
||||
|
||||
typedef void (*Emix_Event_Cb)(void *data, enum Emix_Event event,
|
||||
void *event_info);
|
||||
|
||||
|
@ -109,6 +124,8 @@ typedef struct _Emix_Backend {
|
|||
Emix_Volume volume);
|
||||
|
||||
Evas_Object* (*ebackend_advanced_options_add)(Evas_Object *parent);
|
||||
const Eina_List* (*ebackend_cards_get)(void);
|
||||
Eina_Bool (*ebackend_card_profile_set)(Emix_Card *card, const Emix_Profile *profile);
|
||||
} Emix_Backend;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -168,4 +185,7 @@ E_API void emix_source_volume_set(Emix_Source *source,
|
|||
Emix_Volume volume);
|
||||
E_API Evas_Object* emix_advanced_options_add(Evas_Object *parent);
|
||||
|
||||
E_API const Eina_List* emix_cards_get(void);
|
||||
E_API Eina_Bool emix_card_profile_set(Emix_Card *card, Emix_Profile *profile);
|
||||
|
||||
#endif /* EMIX_H */
|
||||
|
|
Loading…
Reference in New Issue