emixer: pulse: Use description as name for sources

Summary:
Same is already done for sinks.

emixer: Add support to set default sink

emixer: Add support to set default source

emixer: gadget: Update UI to follow pulseaudio default sink changes

Reviewers: devilhorns

Subscribers: abrouwers, netstar, cedric, zmike

Tags: #enlightenment-git

Differential Revision: https://phab.enlightenment.org/D12247
This commit is contained in:
Pau Espin Pedrol 2021-03-02 08:35:21 +00:00 committed by Alastair Poole
parent 06d80f603a
commit b0b2984953
7 changed files with 220 additions and 8 deletions

View File

@ -358,6 +358,10 @@ _sink_event(int type, void *info)
}
else if (type == EMIX_SINK_CHANGED_EVENT)
{
/* If pulseaudio changed the default sink, swap the UI to display it
instead of previously selected sink */
if (sink->default_sink)
_sink_default = sink;
if (_sink_default == sink)
{
static int prev_vol = -1;

View File

@ -25,6 +25,7 @@ typedef struct _Emix_Config_Sink
Eina_List *ports;
int mute;
int volume;
int default_sink;
} Emix_Config_Sink;
typedef struct _Emix_Config_Source
@ -32,6 +33,7 @@ typedef struct _Emix_Config_Source
const char *name;
int mute;
int volume;
int default_source;
} Emix_Config_Source;
typedef struct _Emix_Config_Port
@ -63,11 +65,13 @@ _emix_config_dd_new(void)
E_CONFIG_LIST(c_sinkd, Emix_Config_Sink, ports, c_portd);
E_CONFIG_VAL(c_sinkd, Emix_Config_Sink, mute, INT);
E_CONFIG_VAL(c_sinkd, Emix_Config_Sink, volume, INT);
E_CONFIG_VAL(c_sinkd, Emix_Config_Sink, default_sink, INT);
c_sourced = E_CONFIG_DD_NEW("Emix_Config_Source", Emix_Config_Source);
E_CONFIG_VAL(c_sourced, Emix_Config_Source, name, STR);
E_CONFIG_VAL(c_sourced, Emix_Config_Source, mute, INT);
E_CONFIG_VAL(c_sourced, Emix_Config_Source, volume, INT);
E_CONFIG_VAL(c_sourced, Emix_Config_Source, default_source, INT);
cd = E_CONFIG_DD_NEW("Emix_Config", Emix_Config);
@ -260,6 +264,7 @@ emix_config_save_state_get(void)
if (emsink->volume.channel_count > 0)
sink->volume = emsink->volume.volumes[0];
sink->mute = emsink->mute;
sink->default_sink = emsink->default_sink;
_config->sinks = eina_list_append(_config->sinks, sink);
}
}
@ -274,6 +279,7 @@ emix_config_save_state_get(void)
if (emsource->volume.channel_count > 0)
source->volume = emsource->volume.volumes[0];
source->mute = emsource->mute;
source->default_source = emsource->default_source;
_config->sources = eina_list_append(_config->sources, source);
}
}
@ -351,6 +357,8 @@ emix_config_save_state_restore(void)
free(v.volumes);
}
emix_sink_mute_set(emsink, sink->mute);
if (sink->default_sink)
emix_sink_default_set(emsink);
EINA_LIST_FOREACH(sink->ports, ll, port)
{
if (!port->name) continue;
@ -377,6 +385,8 @@ emix_config_save_state_restore(void)
free(v.volumes);
}
emix_source_mute_set(emsource, source->mute);
if (source->default_source)
emix_source_default_set(emsource);
}
}

View File

@ -121,6 +121,20 @@ _cb_sink_lock_change(void *data,
_emix_sink_volume_fill(sink, fr, bx, lock);
}
static void
_cb_sink_default_change(void *data,
Evas_Object *obj,
void *event_info EINA_UNUSED)
{
Evas_Object *fr = data;
Emix_Sink *sink = evas_object_data_get(fr, "sink");
Eina_Bool is_default = elm_check_state_get(obj);
if (is_default) {
emix_sink_default_set(sink);
elm_object_disabled_set(obj, EINA_TRUE);
}
}
static void
_emix_sink_volume_fill(Emix_Sink *sink, Evas_Object *fr, Evas_Object *bx, Eina_Bool locked)
{
@ -195,6 +209,14 @@ _emix_sink_volume_fill(Emix_Sink *sink, Evas_Object *fr, Evas_Object *bx, Eina_B
elm_box_pack_end(bx, bxhv);
evas_object_show(bxhv);
ck = elm_check_add(bx);
evas_object_data_set(fr, "default", ck);
elm_object_text_set(ck, "Default");
elm_check_state_set(ck, sink->default_sink);
elm_box_pack_end(bxhv, ck);
evas_object_show(ck);
evas_object_smart_callback_add(ck, "changed", _cb_sink_default_change, fr);
ck = elm_check_add(bx);
evas_object_data_set(fr, "mute", ck);
elm_object_text_set(ck, "Mute");
@ -368,6 +390,9 @@ _emix_sink_change(Emix_Sink *sink)
elm_object_disabled_set(sl, sink->mute);
}
ck = evas_object_data_get(fr, "default");
elm_check_state_set(ck, sink->default_sink);
elm_object_disabled_set(ck, sink->default_sink);
}
//////////////////////////////////////////////////////////////////////////////
@ -845,6 +870,20 @@ _cb_source_lock_change(void *data,
_emix_source_volume_fill(source, fr, bx, lock);
}
static void
_cb_source_default_change(void *data,
Evas_Object *obj,
void *event_info EINA_UNUSED)
{
Evas_Object *fr = data;
Emix_Source *source = evas_object_data_get(fr, "source");
Eina_Bool is_default = elm_check_state_get(obj);
if (is_default) {
emix_source_default_set(source);
elm_object_disabled_set(obj, EINA_TRUE);
}
}
static void
_emix_source_volume_fill(Emix_Source *source, Evas_Object *fr, Evas_Object *bx, Eina_Bool locked)
{
@ -925,6 +964,14 @@ _emix_source_volume_fill(Emix_Source *source, Evas_Object *fr, Evas_Object *bx,
elm_box_pack_end(bx, bxhv);
evas_object_show(bxhv);
ck = elm_check_add(bx);
evas_object_data_set(fr, "default", ck);
elm_object_text_set(ck, "Default");
elm_check_state_set(ck, source->default_source);
elm_box_pack_end(bxhv, ck);
evas_object_show(ck);
evas_object_smart_callback_add(ck, "changed", _cb_source_default_change, fr);
ck = elm_check_add(bx);
evas_object_data_set(fr, "mute", ck);
elm_object_text_set(ck, "Mute");
@ -1071,6 +1118,10 @@ _emix_source_change(Emix_Source *source)
elm_slider_value_set(sl, source->volume.volumes[0]);
elm_object_disabled_set(sl, source->mute);
}
ck = evas_object_data_get(fr, "default");
elm_check_state_set(ck, source->default_source);
elm_object_disabled_set(ck, source->default_source);
}
//////////////////////////////////////////////////////////////////////////////

View File

@ -518,7 +518,7 @@ _alsa_backend =
_alsa_shutdown,
_max_volume,
_alsa_sinks_get,
_alsa_support, /*default support*/
_alsa_support, /*sink default support*/
NULL, /*get*/
NULL, /*set*/
_alsa_sink_mute_set, /*mute_set*/
@ -530,6 +530,9 @@ _alsa_backend =
NULL,/*sink input volume set*/
NULL,/*sink input sink change*/
_alsa_sources_get,/*source*/
_alsa_support, /* source default support*/
NULL, /*get*/
NULL, /*set*/
_alsa_sources_mute_set,/* source mute set */
_alsa_sources_volume_set, /* source volume set */
NULL, /* advanced options */

View File

@ -25,7 +25,6 @@ typedef struct _Context
Emix_Event_Cb cb;
const void *userdata;
Ecore_Timer *connect;
int default_sink;
Eina_List *sinks, *sources, *inputs, *cards;
Eina_Bool connected;
@ -35,6 +34,7 @@ typedef struct _Sink
{
Emix_Sink base;
int idx;
const char *pulse_name;
} Sink;
typedef struct _Sink_Input
@ -47,6 +47,7 @@ typedef struct _Source
{
Emix_Source base;
int idx;
const char *pulse_name;
} Source;
typedef struct _Profile
@ -114,6 +115,7 @@ _sink_del(Sink *sink)
eina_stringshare_del(sink->base.volume.channel_names[i]);
free(sink->base.volume.channel_names);
eina_stringshare_del(sink->base.name);
eina_stringshare_del(sink->pulse_name);
free(sink);
}
@ -143,6 +145,7 @@ _source_del(Source *source)
eina_stringshare_del(source->base.volume.channel_names[i]);
free(source->base.volume.channel_names);
eina_stringshare_del(source->base.name);
eina_stringshare_del(source->pulse_name);
free(source);
}
@ -187,6 +190,7 @@ _sink_cb(pa_context *c EINA_UNUSED, const pa_sink_info *info, int eol,
sink = calloc(1, sizeof(Sink));
sink->idx = info->index;
sink->pulse_name = eina_stringshare_add(info->name);
sink->base.name = eina_stringshare_add(info->description);
_pa_cvolume_convert(&info->volume, &sink->base.volume);
sink->base.volume.channel_names = calloc(sink->base.volume.channel_count, sizeof(Emix_Channel));
@ -543,7 +547,8 @@ _source_cb(pa_context *c EINA_UNUSED, const pa_source_info *info,
EINA_SAFETY_ON_NULL_RETURN(source);
source->idx = info->index;
source->base.name = eina_stringshare_add(info->name);
source->pulse_name = eina_stringshare_add(info->name);
source->base.name = eina_stringshare_add(info->description);
_pa_cvolume_convert(&info->volume, &source->base.volume);
source->base.volume.channel_names = calloc(source->base.volume.channel_count, sizeof(Emix_Channel));
for (i = 0; i < source->base.volume.channel_count; ++i)
@ -642,6 +647,9 @@ static void
_sink_default_cb(pa_context *c EINA_UNUSED, const pa_sink_info *info, int eol,
void *userdata EINA_UNUSED)
{
Sink *sink;
Eina_List *l;
if (eol < 0)
{
if (pa_context_errno(c) == PA_ERR_NOENTITY)
@ -657,7 +665,50 @@ _sink_default_cb(pa_context *c EINA_UNUSED, const pa_sink_info *info, int eol,
DBG("sink index: %d\nsink name: %s", info->index,
info->name);
ctx->default_sink = info->index;
EINA_LIST_FOREACH(ctx->sinks, l, sink)
{
Eina_Bool prev_default = sink->base.default_sink;
sink->base.default_sink = (uint32_t)sink->idx == info->index;
if (ctx->cb && prev_default != sink->base.default_sink)
ctx->cb((void *)ctx->userdata, EMIX_SINK_CHANGED_EVENT,
(Emix_Sink *)sink);
}
if (ctx->cb)
ctx->cb((void *)ctx->userdata, EMIX_READY_EVENT, NULL);
}
static void
_source_default_cb(pa_context *c EINA_UNUSED, const pa_source_info *info, int eol,
void *userdata EINA_UNUSED)
{
Source *source;
Eina_List *l;
if (eol < 0)
{
if (pa_context_errno(c) == PA_ERR_NOENTITY)
return;
ERR("Source callback failure");
return;
}
if (eol > 0)
return;
DBG("source index: %d\nsource name: %s", info->index,
info->name);
EINA_LIST_FOREACH(ctx->sources, l, source)
{
Eina_Bool prev_default = source->base.default_source;
source->base.default_source = (uint32_t)source->idx == info->index;
if (ctx->cb && prev_default != source->base.default_source)
ctx->cb((void *)ctx->userdata, EMIX_SOURCE_CHANGED_EVENT,
(Emix_Source *)source);
}
if (ctx->cb)
ctx->cb((void *)ctx->userdata, EMIX_READY_EVENT, NULL);
}
@ -683,6 +734,14 @@ _server_info_cb(pa_context *c, const pa_server_info *info,
return;
}
pa_operation_unref(o);
if (!(o = pa_context_get_source_info_by_name(c, info->default_source_name,
_source_default_cb, userdata)))
{
ERR("pa_context_get_source_info_by_name() failed");
return;
}
pa_operation_unref(o);
}
static int
@ -1369,12 +1428,60 @@ _sink_default_get(void)
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
EINA_LIST_FOREACH(ctx->sinks, l, s)
if (s->idx == ctx->default_sink)
if (s->base.default_sink)
return (Emix_Sink *)s;
return NULL;
}
static void
_sink_default_set(Emix_Sink *sink)
{
Sink *s = (Sink *)sink;
pa_operation* o;
DBG("Set default sink: %s", sink->name);
if (!(o = pa_context_set_default_sink(ctx->context, s->pulse_name, NULL, NULL))) {
ERR("pa_context_set_default_sink() failed");
return;
}
pa_operation_unref(o);
}
static Eina_Bool
_source_default_support(void)
{
return EINA_TRUE;
}
static const Emix_Source *
_source_default_get(void)
{
Source *s;
Eina_List *l;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
EINA_LIST_FOREACH(ctx->sources, l, s)
if (s->base.default_source)
return (Emix_Source *)s;
return NULL;
}
static void
_source_default_set(Emix_Source *source)
{
Source *s = (Source *)source;
pa_operation* o;
DBG("Set default sink: %s", source->name);
if (!(o = pa_context_set_default_source(ctx->context, s->pulse_name, NULL, NULL))) {
ERR("pa_context_set_default_source() failed");
return;
}
pa_operation_unref(o);
}
static Eina_Bool
_sink_change_support(void)
{
@ -1424,7 +1531,7 @@ _pulseaudio_backend =
_sinks_get,
_sink_default_support,
_sink_default_get,
NULL,
_sink_default_set,
_sink_mute_set,
_sink_volume_set,
_sink_port_set,
@ -1434,6 +1541,9 @@ _pulseaudio_backend =
_sink_input_volume_set,
_sink_input_move,
_sources_get,
_source_default_support,
_source_default_get,
_source_default_set,
_source_mute_set,
_source_volume_set,
NULL,

View File

@ -347,6 +347,34 @@ emix_sources_get(void)
return ctx->loaded->ebackend_sources_get();
}
Eina_Bool
emix_source_default_support(void)
{
EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->loaded &&
ctx->loaded->ebackend_source_default_support),
EINA_FALSE);
return ctx->loaded->ebackend_source_default_support();
}
const Emix_Source*
emix_source_default_get(void)
{
EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->loaded &&
ctx->loaded->ebackend_source_default_get),
NULL);
return ctx->loaded->ebackend_source_default_get();
}
void
emix_source_default_set(Emix_Source *source)
{
EINA_SAFETY_ON_FALSE_RETURN((ctx && ctx->loaded &&
ctx->loaded->ebackend_source_default_set &&
source));
ctx->loaded->ebackend_source_default_set(source);
}
void
emix_source_mute_set(Emix_Source *source, Eina_Bool mute)
{
@ -428,5 +456,3 @@ emix_card_profile_set(Emix_Card *card, Emix_Profile *profile)
return ctx->loaded->ebackend_card_profile_set(card, profile);
}

View File

@ -62,6 +62,7 @@ typedef struct _Emix_Sink {
const char *name;
Emix_Volume volume;
Eina_Bool mute;
Eina_Bool default_sink;
Eina_List *ports;
} Emix_Sink;
@ -78,6 +79,7 @@ typedef struct _Emix_Source {
const char *name;
Emix_Volume volume;
Eina_Bool mute;
Eina_Bool default_source;
} Emix_Source;
typedef struct _Emix_Profile {
@ -122,6 +124,9 @@ typedef struct _Emix_Backend {
Emix_Sink_Input *input, Emix_Sink *sink);
const Eina_List* (*ebackend_sources_get)(void);
Eina_Bool (*ebackend_source_default_support)(void);
const Emix_Source* (*ebackend_source_default_get)(void);
void (*ebackend_source_default_set)(Emix_Source *source);
void (*ebackend_source_mute_set)(Emix_Source *source,
Eina_Bool mute);
void (*ebackend_source_volume_set)(Emix_Source *source,
@ -179,6 +184,9 @@ E_API void emix_sink_input_sink_change(Emix_Sink_Input *input,
Emix_Sink *sink);
E_API const Eina_List* emix_sources_get(void);
E_API Eina_Bool emix_source_default_support(void);
E_API const Emix_Source* emix_source_default_get(void);
E_API void emix_source_default_set(Emix_Source *source);
E_API void emix_source_mute_set(Emix_Source *source,
Eina_Bool mute);
E_API void emix_source_volume_set(Emix_Source *source,