Implement background refreshing of audio volume levels
This is still buggy though.
This commit is contained in:
parent
d5c839e321
commit
a0953f5e73
|
@ -239,6 +239,7 @@ static int _channels_get(MixerControlPlugin * channels, va_list properties)
|
|||
value = va_arg(properties, double *);
|
||||
*value = gtk_range_get_value(GTK_RANGE(
|
||||
channels->channels[0].widget));
|
||||
*value = (*value * 255.0) / 100.0;
|
||||
}
|
||||
else if(sscanf(p, "value%zu", &i) == 1)
|
||||
{
|
||||
|
@ -247,6 +248,7 @@ static int _channels_get(MixerControlPlugin * channels, va_list properties)
|
|||
value = va_arg(properties, double *);
|
||||
*value = gtk_range_get_value(GTK_RANGE(
|
||||
channels->channels[i].widget));
|
||||
*value = (*value * 255.0) / 100.0;
|
||||
}
|
||||
/* FIXME implement the rest */
|
||||
else
|
||||
|
@ -353,6 +355,7 @@ static int _set_channels(MixerControlPlugin * channels, size_t cnt)
|
|||
{
|
||||
size_t i;
|
||||
MixerControlChannel * p;
|
||||
gboolean signal = channels->signal;
|
||||
|
||||
/* delete channels as required */
|
||||
if(channels->channels_cnt >= cnt)
|
||||
|
@ -368,6 +371,7 @@ static int _set_channels(MixerControlPlugin * channels, size_t cnt)
|
|||
if((p = realloc(channels->channels, sizeof(*p) * cnt)) == NULL)
|
||||
return -1;
|
||||
channels->channels = p;
|
||||
channels->signal = TRUE;
|
||||
for(i = channels->channels_cnt; i < cnt; i++)
|
||||
{
|
||||
p = &channels->channels[i];
|
||||
|
@ -381,6 +385,7 @@ static int _set_channels(MixerControlPlugin * channels, size_t cnt)
|
|||
gtk_box_pack_start(GTK_BOX(channels->hbox), p->widget, TRUE,
|
||||
TRUE, 0);
|
||||
}
|
||||
channels->signal = signal;
|
||||
if((channels->channels_cnt = cnt) < 2)
|
||||
gtk_widget_hide(channels->bind);
|
||||
else
|
||||
|
@ -419,10 +424,14 @@ static void _set_value(MixerControlPlugin * channels, gdouble value)
|
|||
static void _set_value_channel(MixerControlPlugin * channels,
|
||||
size_t channel, gdouble value)
|
||||
{
|
||||
gboolean signal = channels->signal;
|
||||
|
||||
channels->signal = TRUE;
|
||||
if(channel < channels->channels_cnt)
|
||||
gtk_range_set_value(
|
||||
GTK_RANGE(channels->channels[channel].widget),
|
||||
(value * 100.0) / 255.0);
|
||||
channels->signal = signal;
|
||||
}
|
||||
|
||||
|
||||
|
|
215
src/mixer.c
215
src/mixer.c
|
@ -81,10 +81,8 @@ typedef struct _MixerLevel
|
|||
size_t channels_cnt;
|
||||
} MixerLevel;
|
||||
|
||||
/* FIXME there are two different MixerControl types */
|
||||
typedef struct _MixerControl MixerControl;
|
||||
|
||||
struct _MixerControl
|
||||
/* XXX rename this type */
|
||||
typedef struct _MixerControl2
|
||||
{
|
||||
int index;
|
||||
int type;
|
||||
|
@ -95,7 +93,7 @@ struct _MixerControl
|
|||
} un;
|
||||
|
||||
MixerControl * control;
|
||||
};
|
||||
} MixerControl2;
|
||||
|
||||
struct _Mixer
|
||||
{
|
||||
|
@ -117,8 +115,10 @@ struct _Mixer
|
|||
int fd;
|
||||
#endif
|
||||
|
||||
MixerControl * controls;
|
||||
MixerControl2 * controls;
|
||||
size_t controls_cnt;
|
||||
|
||||
guint source;
|
||||
};
|
||||
|
||||
|
||||
|
@ -126,12 +126,16 @@ struct _Mixer
|
|||
static int _mixer_error(Mixer * mixer, char const * message, int ret);
|
||||
|
||||
/* accessors */
|
||||
static int _mixer_get_control(Mixer * mixer, MixerControl * control);
|
||||
static int _mixer_set_control(Mixer * mixer, MixerControl * control);
|
||||
static int _mixer_get_control(Mixer * mixer, MixerControl2 * control);
|
||||
static int _mixer_set_control(Mixer * mixer, MixerControl2 * control);
|
||||
|
||||
static int _mixer_set_control_widget(Mixer * mixer, MixerControl2 * control);
|
||||
|
||||
static String const * _mixer_get_icon(String const * id);
|
||||
|
||||
/* useful */
|
||||
static int _mixer_refresh_control(Mixer * mixer, MixerControl2 * control);
|
||||
|
||||
static void _mixer_scrolled_window_add(GtkWidget * window, GtkWidget * widget);
|
||||
|
||||
static void _mixer_show_view(Mixer * mixer, int view);
|
||||
|
@ -152,6 +156,8 @@ static MixerControl * _new_set(Mixer * mixer, int index,
|
|||
static MixerControl * _new_value(Mixer * mixer, int index,
|
||||
GtkSizeGroup * vgroup, String const * id, String const * icon,
|
||||
String const * name);
|
||||
/* callbacks */
|
||||
static gboolean _new_on_refresh(gpointer data);
|
||||
|
||||
Mixer * mixer_new(GtkWidget * window, String const * device, MixerLayout layout)
|
||||
{
|
||||
|
@ -164,7 +170,7 @@ Mixer * mixer_new(GtkWidget * window, String const * device, MixerLayout layout)
|
|||
GtkWidget * hvbox = NULL;
|
||||
GtkWidget * hbox;
|
||||
MixerControl * control;
|
||||
MixerControl * q;
|
||||
MixerControl2 * q;
|
||||
int i;
|
||||
#ifdef AUDIO_MIXER_DEVINFO
|
||||
mixer_devinfo_t md;
|
||||
|
@ -194,14 +200,15 @@ Mixer * mixer_new(GtkWidget * window, String const * device, MixerLayout layout)
|
|||
#endif
|
||||
mixer->controls = NULL;
|
||||
mixer->controls_cnt = 0;
|
||||
hgroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
|
||||
vgroup = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL);
|
||||
mixer->source = 0;
|
||||
if(mixer->device == NULL || mixer->fd < 0)
|
||||
{
|
||||
_mixer_error(NULL, device, 0);
|
||||
mixer_delete(mixer);
|
||||
return NULL;
|
||||
}
|
||||
hgroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
|
||||
vgroup = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL);
|
||||
/* widgets */
|
||||
mixer->bold = pango_font_description_new();
|
||||
pango_font_description_set_weight(mixer->bold, PANGO_WEIGHT_BOLD);
|
||||
|
@ -405,6 +412,7 @@ Mixer * mixer_new(GtkWidget * window, String const * device, MixerLayout layout)
|
|||
mixer_show_class(mixer, AudioCoutputs);
|
||||
#endif
|
||||
gtk_widget_show_all(mixer->widget);
|
||||
mixer->source = g_timeout_add(500, _new_on_refresh, mixer);
|
||||
return mixer;
|
||||
}
|
||||
|
||||
|
@ -444,7 +452,7 @@ static MixerControl * _new_enum(Mixer * mixer, int index,
|
|||
struct audio_mixer_enum * e, String const * id,
|
||||
String const * icon, String const * name)
|
||||
{
|
||||
MixerControl mc;
|
||||
MixerControl2 mc;
|
||||
MixerControl * control;
|
||||
int i;
|
||||
char label[16];
|
||||
|
@ -469,7 +477,7 @@ static MixerControl * _new_enum(Mixer * mixer, int index,
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
if(mixercontrol_set(control, "value", mc.un.mask, NULL) != 0)
|
||||
if(_mixer_set_control_widget(mixer, &mc) != 0)
|
||||
{
|
||||
mixercontrol_delete(control);
|
||||
return NULL;
|
||||
|
@ -481,7 +489,7 @@ static MixerControl * _new_set(Mixer * mixer, int index,
|
|||
struct audio_mixer_set * s, String const * id,
|
||||
String const * icon, String const * name)
|
||||
{
|
||||
MixerControl mc;
|
||||
MixerControl2 mc;
|
||||
MixerControl * control;
|
||||
int i;
|
||||
char label[16];
|
||||
|
@ -495,6 +503,7 @@ static MixerControl * _new_set(Mixer * mixer, int index,
|
|||
"set", "members", s->num_mem, NULL))
|
||||
== NULL)
|
||||
return NULL;
|
||||
mc.control = control;
|
||||
for(i = 0; i < s->num_mem; i++)
|
||||
{
|
||||
snprintf(label, sizeof(label), "label%d", i);
|
||||
|
@ -506,7 +515,7 @@ static MixerControl * _new_set(Mixer * mixer, int index,
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
if(mixercontrol_set(control, "value", mc.un.mask, NULL) != 0)
|
||||
if(_mixer_set_control_widget(mixer, &mc) != 0)
|
||||
{
|
||||
mixercontrol_delete(control);
|
||||
return NULL;
|
||||
|
@ -519,12 +528,10 @@ static MixerControl * _new_value(Mixer * mixer, int index,
|
|||
GtkSizeGroup * vgroup, String const * id, String const * icon,
|
||||
String const * name)
|
||||
{
|
||||
MixerControl mc;
|
||||
MixerControl2 mc;
|
||||
MixerControl * control;
|
||||
size_t i;
|
||||
gboolean bind = TRUE;
|
||||
char buf[16];
|
||||
gdouble value;
|
||||
|
||||
mc.index = index;
|
||||
if(_mixer_get_control(mixer, &mc) != 0
|
||||
|
@ -535,6 +542,7 @@ static MixerControl * _new_value(Mixer * mixer, int index,
|
|||
"delta", mc.un.level.delta,
|
||||
"vgroup", vgroup, NULL)) == NULL)
|
||||
return NULL;
|
||||
mc.control = control;
|
||||
/* detect if binding is in place */
|
||||
for(i = 1; i < mc.un.level.channels_cnt; i++)
|
||||
if(mc.un.level.channels[i] != mc.un.level.channels[0])
|
||||
|
@ -542,43 +550,32 @@ static MixerControl * _new_value(Mixer * mixer, int index,
|
|||
bind = FALSE;
|
||||
break;
|
||||
}
|
||||
if(bind)
|
||||
if(mixercontrol_set(control, "bind", bind, NULL) != 0
|
||||
|| _mixer_set_control_widget(mixer, &mc) != 0)
|
||||
{
|
||||
value = mc.un.level.channels[0];
|
||||
if(mixercontrol_set(control, "value", value, "bind", bind, NULL)
|
||||
!= 0)
|
||||
{
|
||||
mixercontrol_delete(control);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mixercontrol_set(control, "bind", bind, NULL) != 0)
|
||||
{
|
||||
mixercontrol_delete(control);
|
||||
return NULL;
|
||||
}
|
||||
for(i = 0; i < mc.un.level.channels_cnt; i++)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "value%zu", i);
|
||||
value = mc.un.level.channels[i];
|
||||
if(mixercontrol_set(control, buf, value, NULL) != 0)
|
||||
{
|
||||
mixercontrol_delete(control);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
mixercontrol_delete(control);
|
||||
return NULL;
|
||||
}
|
||||
return control;
|
||||
}
|
||||
|
||||
/* callbacks */
|
||||
static gboolean _new_on_refresh(gpointer data)
|
||||
{
|
||||
Mixer * mixer = data;
|
||||
|
||||
mixer_refresh(mixer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* mixer_delete */
|
||||
void mixer_delete(Mixer * mixer)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if(mixer->source > 0)
|
||||
g_source_remove(mixer->source);
|
||||
for(i = 0; i < mixer->controls_cnt; i++)
|
||||
mixercontrol_delete(mixer->controls[i]);
|
||||
free(mixer->controls);
|
||||
|
@ -665,8 +662,7 @@ static int _set_channels(Mixer * mixer, MixerControl * control)
|
|||
{
|
||||
size_t i;
|
||||
double value;
|
||||
uint8_t channel;
|
||||
MixerControl mc;
|
||||
MixerControl2 mc;
|
||||
char buf[16];
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -686,12 +682,11 @@ static int _set_channels(Mixer * mixer, MixerControl * control)
|
|||
snprintf(buf, sizeof(buf), "value%zu", i);
|
||||
if(mixercontrol_get(control, buf, &value, NULL) != 0)
|
||||
return -1;
|
||||
channel = (value * 255.0) / 100.0;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() value%zu=%f\n", __func__, i,
|
||||
value);
|
||||
fprintf(stderr, "DEBUG: %s() value%zu=%f\n",
|
||||
__func__, i, value);
|
||||
#endif
|
||||
mc.un.level.channels[i] = channel;
|
||||
mc.un.level.channels[i] = value;
|
||||
}
|
||||
return _mixer_set_control(mixer, &mc);
|
||||
}
|
||||
|
@ -701,7 +696,7 @@ static int _set_mute(Mixer * mixer, MixerControl * control)
|
|||
{
|
||||
size_t i;
|
||||
gboolean value;
|
||||
MixerControl * mc;
|
||||
MixerControl2 * mc;
|
||||
mixer_ctrl_t p;
|
||||
|
||||
# ifdef DEBUG
|
||||
|
@ -730,7 +725,7 @@ static int _set_mute(Mixer * mixer, MixerControl * control)
|
|||
static int _set_radio(Mixer * mixer, MixerControl * control)
|
||||
{
|
||||
size_t i;
|
||||
MixerControl * mc;
|
||||
MixerControl2 * mc;
|
||||
mixer_ctrl_t p;
|
||||
unsigned int value;
|
||||
|
||||
|
@ -761,7 +756,7 @@ static int _set_set(Mixer * mixer, MixerControl * control)
|
|||
{
|
||||
size_t i;
|
||||
unsigned int value;
|
||||
MixerControl * mc;
|
||||
MixerControl2 * mc;
|
||||
mixer_ctrl_t p;
|
||||
|
||||
# ifdef DEBUG
|
||||
|
@ -880,6 +875,18 @@ static gboolean _properties_on_closex(GtkWidget * widget)
|
|||
}
|
||||
|
||||
|
||||
/* mixer_refresh */
|
||||
int mixer_refresh(Mixer * mixer)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < mixer->controls_cnt; i++)
|
||||
ret |= _mixer_refresh_control(mixer, &mixer->controls[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* mixer_show */
|
||||
void mixer_show(Mixer * mixer)
|
||||
{
|
||||
|
@ -965,7 +972,7 @@ static int _error_text(char const * message, int ret)
|
|||
|
||||
/* accessors */
|
||||
/* mixer_get_control */
|
||||
static int _mixer_get_control(Mixer * mixer, MixerControl * control)
|
||||
static int _mixer_get_control(Mixer * mixer, MixerControl2 * control)
|
||||
{
|
||||
#ifdef AUDIO_MIXER_DEVINFO
|
||||
mixer_ctrl_t p;
|
||||
|
@ -1049,14 +1056,24 @@ static int _mixer_get_control(Mixer * mixer, MixerControl * control)
|
|||
# endif
|
||||
#else
|
||||
int value;
|
||||
uint16_t u16;
|
||||
|
||||
if(ioctl(mixer->fd, MIXER_READ(control->index), &value) != 0)
|
||||
return -_mixer_error(NULL, "MIXER_READ", 1);
|
||||
control->type = 0;
|
||||
control->un.level.delta = 1;
|
||||
control->un.level.channels_cnt = 2;
|
||||
control->un.level.channels[0] = ((value & 0xff) * 255) / 100;
|
||||
control->un.level.channels[1] = (((value & 0xff00) >> 8) * 255) / 100;
|
||||
u16 = value & 0xff;
|
||||
u16 = u16 * 255 / 100;
|
||||
control->un.level.channels[0] = u16;
|
||||
u16 = (value & 0xff00) >> 8;
|
||||
u16 = u16 * 255 / 100;
|
||||
control->un.level.channels[1] = u16;
|
||||
# ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() 0x%02x%02x\n", __func__,
|
||||
control->un.level.channels[0],
|
||||
control->un.level.channels[1]);
|
||||
# endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -1101,7 +1118,7 @@ static String const * _mixer_get_icon(String const * id)
|
|||
|
||||
|
||||
/* mixer_set_control */
|
||||
static int _mixer_set_control(Mixer * mixer, MixerControl * control)
|
||||
static int _mixer_set_control(Mixer * mixer, MixerControl2 * control)
|
||||
{
|
||||
#ifdef AUDIO_MIXER_DEVINFO
|
||||
mixer_ctrl_t p;
|
||||
|
@ -1116,9 +1133,14 @@ static int _mixer_set_control(Mixer * mixer, MixerControl * control)
|
|||
return -_mixer_error(mixer, "AUDIO_MIXER_WRITE", 1);
|
||||
#else
|
||||
int level = 0;
|
||||
uint16_t u16;
|
||||
|
||||
level |= (control->un.level.channels[0] * 100) / 255;
|
||||
level |= ((control->un.level.channels[1] * 100) / 255) << 8;
|
||||
u16 = control->un.level.channels[0];
|
||||
u16 = (u16 * 100) / 255;
|
||||
level |= u16;
|
||||
u16 = control->un.level.channels[1];
|
||||
u16 = (u16 * 100) / 255;
|
||||
level |= (u16 << 8);
|
||||
# ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() level=0x%04x\n", __func__, level);
|
||||
# endif
|
||||
|
@ -1129,7 +1151,82 @@ static int _mixer_set_control(Mixer * mixer, MixerControl * control)
|
|||
}
|
||||
|
||||
|
||||
/* mixer_set_control_widget */
|
||||
static int _set_control_widget_channels(MixerControl2 * control);
|
||||
static int _set_control_widget_mute(MixerControl2 * control);
|
||||
static int _set_control_widget_radio(MixerControl2 * control);
|
||||
static int _set_control_widget_set(MixerControl2 * control);
|
||||
|
||||
static int _mixer_set_control_widget(Mixer * mixer, MixerControl2 * control)
|
||||
{
|
||||
String const * type;
|
||||
|
||||
if((type = mixercontrol_get_type(control->control)) == NULL)
|
||||
/* XXX report error */
|
||||
return -1;
|
||||
if(string_compare(type, "channels") == 0)
|
||||
return _set_control_widget_channels(control);
|
||||
if(string_compare(type, "mute") == 0)
|
||||
return _set_control_widget_mute(control);
|
||||
if(string_compare(type, "radio") == 0)
|
||||
return _set_control_widget_radio(control);
|
||||
if(string_compare(type, "set") == 0)
|
||||
return _set_control_widget_set(control);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _set_control_widget_channels(MixerControl2 * control)
|
||||
{
|
||||
gboolean bind;
|
||||
gdouble value;
|
||||
size_t i;
|
||||
char buf[16];
|
||||
|
||||
if(mixercontrol_get(control->control, "bind", &bind, NULL) != 0)
|
||||
return -1;
|
||||
if(bind)
|
||||
{
|
||||
value = control->un.level.channels[0];
|
||||
return mixercontrol_set(control->control, "value", value, NULL);
|
||||
}
|
||||
for(i = 0; i < control->un.level.channels_cnt; i++)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "value%zu", i);
|
||||
value = control->un.level.channels[i];
|
||||
if(mixercontrol_set(control->control, buf, value, NULL)
|
||||
!= 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _set_control_widget_mute(MixerControl2 * control)
|
||||
{
|
||||
/* FIXME implement */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _set_control_widget_radio(MixerControl2 * control)
|
||||
{
|
||||
return mixercontrol_set(control->control, "value", control->un.mask,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int _set_control_widget_set(MixerControl2 * control)
|
||||
{
|
||||
return mixercontrol_set(control->control, "value", control->un.mask,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
/* useful */
|
||||
/* mixer_refresh_control */
|
||||
static int _mixer_refresh_control(Mixer * mixer, MixerControl2 * control)
|
||||
{
|
||||
return _mixer_set_control_widget(mixer, control);
|
||||
}
|
||||
|
||||
|
||||
/* mixer_scrolled_window_add */
|
||||
static void _mixer_scrolled_window_add(GtkWidget * window, GtkWidget * widget)
|
||||
{
|
||||
|
|
|
@ -68,6 +68,8 @@ int mixer_set(Mixer * mixer, MixerControl * control);
|
|||
/* useful */
|
||||
void mixer_properties(Mixer * mixer);
|
||||
|
||||
int mixer_refresh(Mixer * mixer);
|
||||
|
||||
void mixer_show(Mixer * mixer);
|
||||
void mixer_show_all(Mixer * mixer);
|
||||
void mixer_show_class(Mixer * mixer, String const * name);
|
||||
|
|
Loading…
Reference in New Issue
Block a user