From: Takashi Iwai Date: Mon, 9 Jul 2001 08:36:08 +0000 (+0000) Subject: Added ADC/DAC volume controls X-Git-Tag: v1.0.3~148 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=0ebaf0d04e8661e2077e96abb9034b129692ca6e;p=alsa-tools.git Added ADC/DAC volume controls --- diff --git a/envy24control/Makefile.am b/envy24control/Makefile.am index 8708de1..af36056 100644 --- a/envy24control/Makefile.am +++ b/envy24control/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS = envy24control envy24control_SOURCES = envy24control.c envy24control.h levelmeters.c \ - mixer.c patchbay.c hardware.c driverevents.c + mixer.c patchbay.c hardware.c driverevents.c volume.c envy24control_LDFLAGS = $(GTK_LIBS) EXTRA_DIST = cvscompile diff --git a/envy24control/driverevents.c b/envy24control/driverevents.c index 45cfd22..3818f22 100644 --- a/envy24control/driverevents.c +++ b/envy24control/driverevents.c @@ -62,6 +62,14 @@ void control_input_callback(gpointer data, gint source, GdkInputCondition condit patchbay_update(); else if (!strcmp(name, "IEC958 Playback Route")) patchbay_update(); + else if (!strcmp(name, "DAC Volume")) + dac_volume_update(index); + else if (!strcmp(name, "ADC Volume")) + adc_volume_update(index); + else if (!strcmp(name, "Output Sensitivity Switch")) + dac_sense_update(index); + else if (!strcmp(name, "Input Sensitivity Switch")) + adc_sense_update(index); break; default: break; diff --git a/envy24control/envy24control.c b/envy24control/envy24control.c index 81570c3..8f524d8 100644 --- a/envy24control/envy24control.c +++ b/envy24control/envy24control.c @@ -76,6 +76,10 @@ GtkWidget *hw_spdif_output_notebook; GtkWidget *hw_spdif_input_coaxial_radio; GtkWidget *hw_spdif_input_optical_radio; +GtkObject *av_dac_volume_adj[10]; +GtkObject *av_adc_volume_adj[10]; +GtkWidget *av_dac_sense_radio[10][4]; +GtkWidget *av_adc_sense_radio[10][4]; static void create_mixer_frame(GtkWidget *fixed, int stream) @@ -1005,6 +1009,123 @@ static void create_about(GtkWidget *main, GtkWidget *notebook, int page) gtk_widget_set_usize(label, 736, 16); } +static void create_analog_volume(GtkWidget *main, GtkWidget *notebook, int page) +{ + GtkWidget *label; + GtkWidget *fixed; + GtkWidget *fixed1; + GtkWidget *frame; + GtkObject *adj; + GtkWidget *vscale; + GtkWidget *radio; + GSList *group; + GtkWidget *scrollwin; + GtkWidget *viewport; + int i, j; + + scrollwin = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(scrollwin); + gtk_container_add(GTK_CONTAINER(notebook), scrollwin); + + label = gtk_label_new("Analog Volume"); + gtk_widget_show(label); + gtk_notebook_set_tab_label(GTK_NOTEBOOK(notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page), label); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER); + viewport = gtk_viewport_new(NULL, NULL); + gtk_widget_show(viewport); + gtk_container_add(GTK_CONTAINER(scrollwin), viewport); + + fixed = gtk_fixed_new(); + gtk_widget_show(fixed); + gtk_container_add(GTK_CONTAINER(viewport), fixed); + + /* create DAC */ + for (i = 0; i < envy_dac_volumes(); i++) { + char name[32]; + sprintf(name, "DAC %d", i); + frame = gtk_frame_new(name); + gtk_widget_show(frame); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); + gtk_fixed_put(GTK_FIXED(fixed), frame, 2 + i * 74, 2); + gtk_widget_set_uposition(frame, 2 + i * 74, 2); + gtk_widget_set_usize(frame, 70, 288); + + fixed1 = gtk_fixed_new(); + gtk_widget_show(fixed1); + gtk_container_add(GTK_CONTAINER(frame), fixed1); + + adj = gtk_adjustment_new(0, -127, 0, 1, 16, 0); + av_dac_volume_adj[i] = adj; + vscale = gtk_vscale_new(GTK_ADJUSTMENT(adj)); + gtk_scale_set_draw_value(GTK_SCALE(vscale), FALSE); + gtk_widget_show(vscale); + gtk_fixed_put(GTK_FIXED(fixed1), vscale, 2, 2); + gtk_widget_set_usize(vscale, 66, 200); + + gtk_scale_set_value_pos(GTK_SCALE(vscale), GTK_POS_BOTTOM); + gtk_scale_set_digits(GTK_SCALE(vscale), 0); + gtk_signal_connect(GTK_OBJECT(adj), "value_changed", + GTK_SIGNAL_FUNC(dac_volume_adjust), (gpointer)(i)); + if (i >= envy_dac_senses()) + continue; + group = NULL; + for (j = 0; j < envy_dac_sense_items(); j++) { + radio = gtk_radio_button_new_with_label(group, envy_dac_sense_enum_name(j)); + av_dac_sense_radio[i][j] = radio; + gtk_widget_show(radio); + gtk_signal_connect(GTK_OBJECT(radio), "toggled", + (GtkSignalFunc)dac_sense_toggled, (gpointer)((i << 8) + j)); + gtk_fixed_put(GTK_FIXED(fixed1), radio, 2, 202 + j * 20); + gtk_widget_set_usize(radio, 66, 24); + group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio)); + } + } + + /* create ADC */ + for (i = 0; i < envy_adc_volumes(); i++) { + char name[32]; + sprintf(name, "ADC %d", i); + frame = gtk_frame_new(name); + gtk_widget_show(frame); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); + gtk_fixed_put(GTK_FIXED(fixed), frame, 2 + (i + envy_dac_volumes()) * 74, 2); + gtk_widget_set_uposition(frame, 2 + (i + envy_dac_volumes()) * 74, 2); + gtk_widget_set_usize(frame, 70, 288); + + fixed1 = gtk_fixed_new(); + gtk_widget_show(fixed1); + gtk_container_add(GTK_CONTAINER(frame), fixed1); + + adj = gtk_adjustment_new(0, -127, 0, 1, 16, 0); + av_adc_volume_adj[i] = adj; + vscale = gtk_vscale_new(GTK_ADJUSTMENT(adj)); + gtk_scale_set_draw_value(GTK_SCALE(vscale), FALSE); + gtk_widget_show(vscale); + gtk_fixed_put(GTK_FIXED(fixed1), vscale, 2, 2); + gtk_widget_set_usize(vscale, 66, 200); + + gtk_scale_set_value_pos(GTK_SCALE(vscale), GTK_POS_BOTTOM); + gtk_scale_set_digits(GTK_SCALE(vscale), 0); + gtk_signal_connect(GTK_OBJECT(adj), "value_changed", + GTK_SIGNAL_FUNC(adc_volume_adjust), (gpointer)(i)); + if (i >= envy_adc_senses()) + continue; + group = NULL; + for (j = 0; j < envy_adc_sense_items(); j++) { + radio = gtk_radio_button_new_with_label(group, envy_adc_sense_enum_name(j)); + av_adc_sense_radio[i][j] = radio; + gtk_widget_show(radio); + gtk_signal_connect(GTK_OBJECT(radio), "toggled", + (GtkSignalFunc)adc_sense_toggled, (gpointer)((i << 8) + j)); + gtk_fixed_put(GTK_FIXED(fixed1), radio, 2, 202 + j * 20); + gtk_widget_set_usize(radio, 66, 24); + group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio)); + } + } +} + + static void usage(void) { fprintf(stderr, "usage: envy24control [-D control-name]\n"); @@ -1015,12 +1136,11 @@ int main(int argc, char **argv) GtkWidget *notebook; char *name, title[128]; int i, c, err; - //snd_ctl_t *ctl; // global snd_ctl_card_info_t *hw_info; snd_ctl_elem_value_t *val; int npfds; struct pollfd *pfds; - // snd_mixer_filter_t filter; + int page; static struct option long_options[] = { {"device", 1, 0, 'D'}, }; @@ -1069,6 +1189,7 @@ int main(int argc, char **argv) level_meters_init(); patchbay_init(); hardware_init(); + analog_volume_init(); /* Make the title */ sprintf(title, "Envy24 Control Utility %s (%s)", VERSION, snd_ctl_card_info_get_longname(hw_info)); @@ -1089,10 +1210,13 @@ int main(int argc, char **argv) gtk_widget_show(notebook); gtk_container_add(GTK_CONTAINER(window), notebook); - create_mixer(window, notebook, 0); - create_router(window, notebook, 1); - create_hardware(window, notebook, 2); - create_about(window, notebook, 3); + page = 0; + create_mixer(window, notebook, page++); + create_router(window, notebook, page++); + create_hardware(window, notebook, page++); + if (envy_analog_volume_available()) + create_analog_volume(window, notebook, page++); + create_about(window, notebook, page++); npfds = snd_ctl_poll_descriptors_count(ctl); if (npfds > 0) { @@ -1112,6 +1236,7 @@ int main(int argc, char **argv) mixer_postinit(); patchbay_postinit(); hardware_postinit(); + analog_volume_postinit(); gtk_widget_show(window); gtk_main(); diff --git a/envy24control/envy24control.h b/envy24control/envy24control.h index d96a9b6..0487cb8 100644 --- a/envy24control/envy24control.h +++ b/envy24control/envy24control.h @@ -85,6 +85,10 @@ extern GtkWidget *hw_spdif_output_notebook; extern GtkWidget *hw_spdif_input_coaxial_radio; extern GtkWidget *hw_spdif_input_optical_radio; +extern GtkObject *av_dac_volume_adj[]; +extern GtkObject *av_adc_volume_adj[]; +extern GtkWidget *av_dac_sense_radio[][4]; +extern GtkWidget *av_adc_sense_radio[][4]; gint level_meters_configure_event(GtkWidget *widget, GdkEventConfigure *event); gint level_meters_expose_event(GtkWidget *widget, GdkEventExpose *event); @@ -123,6 +127,26 @@ void spdif_input_update(void); void spdif_input_toggled(GtkWidget *togglebutton, gpointer data); void hardware_init(void); void hardware_postinit(void); +void analog_volume_init(void); +void analog_volume_postinit(void); +int envy_dac_volumes(void); +int envy_adc_volumes(void); +int envy_dac_senses(void); +int envy_adc_senses(void); +int envy_dac_sense_items(void); +int envy_adc_sense_items(void); +const char *envy_dac_sense_enum_name(int i); +const char *envy_adc_sense_enum_name(int i); +int envy_analog_volume_available(void); + +void dac_volume_update(int idx); +void adc_volume_update(int idx); +void dac_sense_update(int idx); +void adc_sense_update(int idx); +void dac_volume_adjust(GtkAdjustment *adj, gpointer data); +void adc_volume_adjust(GtkAdjustment *adj, gpointer data); +void dac_sense_toggled(GtkWidget *togglebutton, gpointer data); +void adc_sense_toggled(GtkWidget *togglebutton, gpointer data); void control_input_callback(gpointer data, gint source, GdkInputCondition condition); void mixer_input_callback(gpointer data, gint source, GdkInputCondition condition); diff --git a/envy24control/volume.c b/envy24control/volume.c new file mode 100644 index 0000000..5a3e251 --- /dev/null +++ b/envy24control/volume.c @@ -0,0 +1,303 @@ +/* + * volume.c - analog volume settings + * + * This code is added by Takashi Iwai + * + * Copyright (c) 2000 Jaroslav Kysela + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "envy24control.h" + +#define toggle_set(widget, state) \ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), state); + +#define DAC_VOLUME_NAME "DAC Volume" +#define ADC_VOLUME_NAME "ADC Volume" +#define DAC_SENSE_NAME "Output Sensitivity Switch" +#define ADC_SENSE_NAME "Input Sensitivity Switch" + +static int dac_volumes; +static int adc_volumes; +static int dac_senses; +static int adc_senses; +static int dac_sense_items; +static int adc_sense_items; +static char *dac_sense_name[4]; +static char *adc_sense_name[4]; + +int envy_dac_volumes(void) +{ + return dac_volumes; +} + +int envy_adc_volumes(void) +{ + return adc_volumes; +} + +int envy_dac_senses(void) +{ + return dac_senses; +} + +int envy_adc_senses(void) +{ + return adc_senses; +} + +int envy_dac_sense_items(void) +{ + return dac_sense_items; +} + +int envy_adc_sense_items(void) +{ + return adc_sense_items; +} + +const char *envy_dac_sense_enum_name(int i) +{ + return dac_sense_name[i]; +} + +const char *envy_adc_sense_enum_name(int i) +{ + return adc_sense_name[i]; +} + +int envy_analog_volume_available(void) +{ + return dac_volumes > 0 || adc_volumes > 0; +} + + +/* + */ + +void dac_volume_update(int idx) +{ + snd_ctl_elem_value_t *val; + int err; + snd_ctl_elem_value_alloca(&val); + snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_value_set_name(val, DAC_VOLUME_NAME); + snd_ctl_elem_value_set_index(val, idx); + if ((err = snd_ctl_elem_read(ctl, val)) < 0) { + g_print("Unable to read dac volume: %s\n", snd_strerror(err)); + return; + } + gtk_adjustment_set_value(GTK_ADJUSTMENT(av_dac_volume_adj[idx]), + -snd_ctl_elem_value_get_integer(val, 0)); +} + +void adc_volume_update(int idx) +{ + snd_ctl_elem_value_t *val; + int err; + snd_ctl_elem_value_alloca(&val); + snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_value_set_name(val, ADC_VOLUME_NAME); + snd_ctl_elem_value_set_index(val, idx); + if ((err = snd_ctl_elem_read(ctl, val)) < 0) { + g_print("Unable to read adc volume: %s\n", snd_strerror(err)); + return; + } + gtk_adjustment_set_value(GTK_ADJUSTMENT(av_adc_volume_adj[idx]), + -snd_ctl_elem_value_get_integer(val, 0)); +} + +void dac_sense_update(int idx) +{ + snd_ctl_elem_value_t *val; + int err; + int state; + snd_ctl_elem_value_alloca(&val); + snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_value_set_name(val, DAC_SENSE_NAME); + snd_ctl_elem_value_set_index(val, idx); + if ((err = snd_ctl_elem_read(ctl, val)) < 0) { + g_print("Unable to read dac sense: %s\n", snd_strerror(err)); + return; + } + state = snd_ctl_elem_value_get_enumerated(val, 0); + toggle_set(av_dac_sense_radio[idx][state], TRUE); +} + +void adc_sense_update(int idx) +{ + snd_ctl_elem_value_t *val; + int err; + int state; + snd_ctl_elem_value_alloca(&val); + snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_value_set_name(val, ADC_SENSE_NAME); + snd_ctl_elem_value_set_index(val, idx); + if ((err = snd_ctl_elem_read(ctl, val)) < 0) { + g_print("Unable to read adc sense: %s\n", snd_strerror(err)); + return; + } + state = snd_ctl_elem_value_get_enumerated(val, 0); + toggle_set(av_adc_sense_radio[idx][state], TRUE); +} + + +/* + */ + +void dac_volume_adjust(GtkAdjustment *adj, gpointer data) +{ + int idx = (int)data; + snd_ctl_elem_value_t *val; + int err; + + snd_ctl_elem_value_alloca(&val); + snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_value_set_name(val, DAC_VOLUME_NAME); + snd_ctl_elem_value_set_index(val, idx); + snd_ctl_elem_value_set_integer(val, 0, -(int)adj->value); + if ((err = snd_ctl_elem_write(ctl, val)) < 0) + g_print("Unable to write dac volume: %s\n", snd_strerror(err)); +} + +void adc_volume_adjust(GtkAdjustment *adj, gpointer data) +{ + int idx = (int)data; + snd_ctl_elem_value_t *val; + int err; + + snd_ctl_elem_value_alloca(&val); + snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_value_set_name(val, ADC_VOLUME_NAME); + snd_ctl_elem_value_set_index(val, idx); + snd_ctl_elem_value_set_integer(val, 0, -(int)adj->value); + if ((err = snd_ctl_elem_write(ctl, val)) < 0) + g_print("Unable to write adc volume: %s\n", snd_strerror(err)); +} + +void dac_sense_toggled(GtkWidget *togglebutton, gpointer data) +{ + int idx = (long)data >> 8; + int state = (long)data & 0xff; + snd_ctl_elem_value_t *val; + int err; + + snd_ctl_elem_value_alloca(&val); + snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_value_set_name(val, DAC_SENSE_NAME); + snd_ctl_elem_value_set_index(val, idx); + snd_ctl_elem_value_set_enumerated(val, 0, state); + if ((err = snd_ctl_elem_write(ctl, val)) < 0) + g_print("Unable to write dac sense: %s\n", snd_strerror(err)); +} + +void adc_sense_toggled(GtkWidget *togglebutton, gpointer data) +{ + int idx = (long)data >> 8; + int state = (long)data & 0xff; + snd_ctl_elem_value_t *val; + int err; + + snd_ctl_elem_value_alloca(&val); + snd_ctl_elem_value_set_interface(val, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_value_set_name(val, ADC_SENSE_NAME); + snd_ctl_elem_value_set_index(val, idx); + snd_ctl_elem_value_set_enumerated(val, 0, state); + if ((err = snd_ctl_elem_write(ctl, val)) < 0) + g_print("Unable to write adc sense: %s\n", snd_strerror(err)); +} + +/* + */ + +void analog_volume_init(void) +{ + snd_ctl_elem_info_t *info; + int i; + + snd_ctl_elem_info_alloca(&info); + + snd_ctl_elem_info_set_interface(info, SND_CTL_ELEM_IFACE_MIXER); + for (i = 0; i < 10; i++) { + snd_ctl_elem_info_set_name(info, DAC_VOLUME_NAME); + snd_ctl_elem_info_set_numid(info, 0); + snd_ctl_elem_info_set_index(info, i); + if (snd_ctl_elem_info(ctl, info) < 0) + break; + } + dac_volumes = i; + snd_ctl_elem_info_set_name(info, DAC_SENSE_NAME); + for (i = 0; i < dac_volumes; i++) { + snd_ctl_elem_info_set_numid(info, 0); + snd_ctl_elem_info_set_index(info, i); + if (snd_ctl_elem_info(ctl, info) < 0) + break; + } + dac_senses = i; + if (dac_senses > 0) { + snd_ctl_elem_info_set_numid(info, 0); + snd_ctl_elem_info_set_index(info, 0); + snd_ctl_elem_info(ctl, info); + dac_sense_items = snd_ctl_elem_info_get_items(info); + for (i = 0; i < dac_sense_items; i++) { + snd_ctl_elem_info_set_item(info, i); + snd_ctl_elem_info(ctl, info); + dac_sense_name[i] = strdup(snd_ctl_elem_info_get_item_name(info)); + } + } + + for (i = 0; i < 10; i++) { + snd_ctl_elem_info_set_name(info, ADC_VOLUME_NAME); + snd_ctl_elem_info_set_numid(info, 0); + snd_ctl_elem_info_set_index(info, i); + if (snd_ctl_elem_info(ctl, info) < 0) + break; + } + adc_volumes = i; + snd_ctl_elem_info_set_name(info, ADC_SENSE_NAME); + for (i = 0; i < adc_volumes; i++) { + snd_ctl_elem_info_set_numid(info, 0); + snd_ctl_elem_info_set_index(info, i); + if (snd_ctl_elem_info(ctl, info) < 0) + break; + } + adc_senses = i; + if (adc_senses > 0) { + snd_ctl_elem_info_set_numid(info, 0); + snd_ctl_elem_info_set_index(info, 0); + snd_ctl_elem_info(ctl, info); + adc_sense_items = snd_ctl_elem_info_get_items(info); + for (i = 0; i < adc_sense_items; i++) { + snd_ctl_elem_info_set_item(info, i); + snd_ctl_elem_info(ctl, info); + adc_sense_name[i] = strdup(snd_ctl_elem_info_get_item_name(info)); + } + } +} + +void analog_volume_postinit(void) +{ + int i; + + for (i = 0; i < dac_volumes; i++) + dac_volume_update(i); + for (i = 0; i < adc_volumes; i++) + adc_volume_update(i); + for (i = 0; i < dac_senses; i++) + dac_sense_update(i); + for (i = 0; i < adc_senses; i++) + adc_sense_update(i); +}