summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--voss_devctl_gtk.c180
1 files changed, 135 insertions, 45 deletions
diff --git a/voss_devctl_gtk.c b/voss_devctl_gtk.c
index 3066fdf..6bbef1e 100644
--- a/voss_devctl_gtk.c
+++ b/voss_devctl_gtk.c
@@ -32,40 +32,80 @@ char voss_opts[2] = {
[DEVTYPE_REC] = 'R'
};
-struct device_selection_cb_data {
+struct device_controls_cb_data {
GtkWidget *combo;
+ GtkWidget *slider;
int type;
};
static void
-voss_cmd_from_selections(GtkWidget *combo, int type)
+update_volume_slider(GtkWidget *slider, int type)
+{
+ char devnode_mixer[PATH_MAX];
+ unsigned int devnum;
+ size_t len = sizeof(int);
+ int mixer_fd, pcm_curr, vol_curr;
+
+ /* associate mixer to dsp */
+ sysctlbyname("hw.snd.default_unit", &devnum, &len, NULL, len);
+ snprintf(devnode_mixer, PATH_MAX, "/dev/mixer%u", devnum);
+
+ gdouble vol_avg = 0.0;
+
+ if (type == DEVTYPE_PLAY) {
+ if ((mixer_fd = open(devnode_mixer, O_RDONLY, 0)) > 0) {
+ ioctl(mixer_fd, MIXER_READ(SOUND_MIXER_VOLUME), &vol_curr);
+ ioctl(mixer_fd, MIXER_READ(SOUND_MIXER_PCM), &pcm_curr);
+ /* average of 4 channels - vol/pcm left/right */
+ vol_avg = (double)((((vol_curr & 0xff) + ((vol_curr >> 8) & 0xff))
+ + ((pcm_curr & 0xff) + ((pcm_curr >> 8) & 0xff))) >> 2);
+ (void)close(mixer_fd);
+ }
+ } else if (type == DEVTYPE_REC) {
+ if ((mixer_fd = open(devnode_mixer, O_RDONLY, 0)) > 0) {
+ ioctl(mixer_fd, MIXER_READ(SOUND_MIXER_MIC), &vol_curr);
+ /* average of 2 channels - left/right */
+ vol_avg = (double)(((vol_curr & 0xff) + ((vol_curr >> 8) & 0xff)) >> 1);
+ (void)close(mixer_fd);
+ }
+ }
+
+ if (vol_avg) {
+ gtk_range_set_value(GTK_RANGE(slider), vol_avg);
+ }
+}
+
+
+static void
+apply_device_selections(GtkWidget *combo, int type)
{
GtkTreeModel *model;
GtkTreeIter iter;
- gchar *oss_devnode;
- int voss_dsp_fd;
+ gchar *devnode_oss;
+ int voss_ctrl_fd;
char options[VIRTUAL_OSS_OPTIONS_MAX];
if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) {
model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
- gtk_tree_model_get(model, &iter, COL_VALUE, &oss_devnode, -1);
+ gtk_tree_model_get(model, &iter, COL_VALUE, &devnode_oss, -1);
- if ((voss_dsp_fd = open(VOSS_DEV, O_WRONLY)) > 0) {
+ if ((voss_ctrl_fd = open(VOSS_DEV, O_WRONLY)) > 0) {
snprintf(options, VIRTUAL_OSS_OPTIONS_MAX,
- "-%c %s", voss_opts[type], oss_devnode);
- ioctl(voss_dsp_fd, VIRTUAL_OSS_ADD_OPTIONS, &options);
- close(voss_dsp_fd);
+ "-%c %s", voss_opts[type], devnode_oss);
+ ioctl(voss_ctrl_fd, VIRTUAL_OSS_ADD_OPTIONS, &options);
+ close(voss_ctrl_fd);
}
/* set the default mixer device - playback only */
unsigned int devnum;
size_t len = sizeof(int);
- if (type == DEVTYPE_PLAY && sscanf(oss_devnode, "/dev/dsp%u", &devnum)) {
+ if ((type == DEVTYPE_PLAY)
+ && (sscanf(devnode_oss, "/dev/dsp%u", &devnum) == 1)) {
sysctlbyname("hw.snd.default_unit", NULL, &len, &devnum, len);
}
- g_free(oss_devnode);
+ g_free(devnode_oss);
}
}
@@ -73,28 +113,29 @@ voss_cmd_from_selections(GtkWidget *combo, int type)
static void
cb_toggle_enabled(GtkToggleButton *button, gpointer user_data)
{
- struct device_selection_cb_data *data = user_data;
+ struct device_controls_cb_data *data = user_data;
gboolean checked = gtk_toggle_button_get_active(button);
assert(data->type < _NUM_DEVTYPES);
/* disable the combo when checked */
gtk_widget_set_sensitive(data->combo, !checked);
+ gtk_widget_set_sensitive(GTK_WIDGET(data->slider), !checked);
char options[VIRTUAL_OSS_OPTIONS_MAX];
- int voss_dsp_fd;
+ int voss_ctrl_fd;
/* if disabled, set to /dev/null */
if (checked) {
- if ((voss_dsp_fd = open(VOSS_DEV, O_WRONLY)) > 0) {
+ if ((voss_ctrl_fd = open(VOSS_DEV, O_WRONLY)) > 0) {
snprintf(options, VIRTUAL_OSS_OPTIONS_MAX,
"-%c /dev/null", voss_opts[data->type]);
- ioctl(voss_dsp_fd, VIRTUAL_OSS_ADD_OPTIONS, &options);
- close(voss_dsp_fd);
+ ioctl(voss_ctrl_fd, VIRTUAL_OSS_ADD_OPTIONS, &options);
+ close(voss_ctrl_fd);
}
- }
- else {
- voss_cmd_from_selections(GTK_WIDGET(data->combo), data->type);
+ } else {
+ apply_device_selections(GTK_WIDGET(data->combo), data->type);
+ update_volume_slider(GTK_WIDGET(data->slider), data->type);
}
}
@@ -103,9 +144,44 @@ static void
cb_dev_selected(GtkComboBox *combo, gpointer user_data)
{
int type = GPOINTER_TO_INT(user_data);
- printf("%d\n", type);
assert(type == DEVTYPE_PLAY || type == DEVTYPE_REC);
- voss_cmd_from_selections(GTK_WIDGET(combo), type);
+ apply_device_selections(GTK_WIDGET(combo), type);
+}
+
+
+static gboolean
+cb_volume_set(GtkWidget *slider, GdkEventButton *event, gpointer user_data)
+{
+ char devnode_mixer[PATH_MAX];
+ unsigned int devnum;
+ size_t len = sizeof(int);
+ int mixer_fd, vol_targ, slider_val;
+
+ (void)event; //unused
+ unsigned int type = GPOINTER_TO_INT(user_data);
+
+ /* associate mixer to dsp */
+ sysctlbyname("hw.snd.default_unit", &devnum, &len, NULL, len);
+ snprintf(devnode_mixer, PATH_MAX, "/dev/mixer%u", devnum);
+
+ slider_val = (int)gtk_range_get_value(GTK_RANGE(slider));
+ vol_targ = slider_val | (slider_val << 8);
+
+ if (type == DEVTYPE_PLAY) {
+ if ((mixer_fd = open(devnode_mixer, O_WRONLY, 0)) > 0) {
+ ioctl(mixer_fd, SOUND_MIXER_WRITE_VOLUME, (int *)&vol_targ);
+ ioctl(mixer_fd, SOUND_MIXER_WRITE_PCM, (int *)&vol_targ);
+ (void)close(mixer_fd);
+ }
+ } else if (type == DEVTYPE_REC) {
+ if ((mixer_fd = open(devnode_mixer, O_WRONLY, 0)) > 0) {
+ ioctl(mixer_fd, SOUND_MIXER_WRITE_MIC, (int *)&vol_targ);
+ (void)close(mixer_fd);
+ }
+ }
+
+ /* button release callback needs a return value */
+ return FALSE;
}
@@ -145,8 +221,8 @@ combo_select_by_value(GtkWidget *combo, const char *val_target)
static void
-setup_device_selection(GtkListStore *store, GtkWidget *combo,
- GtkWidget *check, int type)
+setup_device_controls(GtkListStore *store, GtkWidget *combo,
+ GtkWidget *check, GtkWidget *slider, int type)
{
assert(type < _NUM_DEVTYPES);
@@ -187,66 +263,72 @@ setup_device_selection(GtkListStore *store, GtkWidget *combo,
close(oss_dsp_fd);
struct virtual_oss_system_info vsi;
- int voss_dsp_fd;
+ int voss_ctrl_fd;
char options[VIRTUAL_OSS_OPTIONS_MAX];
/* the same for Virtual OSS */
- if ((voss_dsp_fd = open(VOSS_DEV, O_WRONLY)) == -1) {
+ if ((voss_ctrl_fd = open(VOSS_DEV, O_WRONLY)) == -1) {
printf("Failed to open device %s: %s\n",
VOSS_DEV, strerror(errno));
}
- if (ioctl(voss_dsp_fd, VIRTUAL_OSS_GET_SYSTEM_INFO, &vsi) < 0) {
+ if (ioctl(voss_ctrl_fd, VIRTUAL_OSS_GET_SYSTEM_INFO, &vsi) < 0) {
printf("Cannot get Virtual OSS system info: %s\n",
strerror(errno));
}
- close(voss_dsp_fd);
+ close(voss_ctrl_fd);
char current_dev[OSS_DEVNODE_SIZE];
if (type == DEVTYPE_PLAY) {
strncpy(current_dev, vsi.tx_device_name, OSS_DEVNODE_SIZE);
- }
- else if (type == DEVTYPE_REC) {
+ } else if (type == DEVTYPE_REC) {
strncpy(current_dev, vsi.rx_device_name, OSS_DEVNODE_SIZE);
}
bool active = true;
if (strncmp("/dev/null", current_dev, OSS_DEVNODE_SIZE)) {
combo_select_by_value(combo, current_dev);
- }
- else {
+ } else {
active = false;
}
/* if no match and not already /dev/null, revert to /dev/null */
if (active && gtk_combo_box_get_active(GTK_COMBO_BOX(combo)) < 0) {
active = false;
- if ((voss_dsp_fd = open(VOSS_DEV, O_WRONLY)) > 0) {
+ if ((voss_ctrl_fd = open(VOSS_DEV, O_WRONLY)) > 0) {
snprintf(options, VIRTUAL_OSS_OPTIONS_MAX,
"-%c /dev/null", voss_opts[type]);
- ioctl(voss_dsp_fd, VIRTUAL_OSS_ADD_OPTIONS, &options);
- close(voss_dsp_fd);
+ ioctl(voss_ctrl_fd, VIRTUAL_OSS_ADD_OPTIONS, &options);
+ close(voss_ctrl_fd);
}
}
if (!active) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
gtk_widget_set_sensitive(combo, FALSE);
+ gtk_widget_set_sensitive(slider, FALSE);
gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
}
- struct device_selection_cb_data *data = g_new(struct device_selection_cb_data, 1);
- data->combo = combo;
- data->type = type;
-
GtkCellRenderer *render = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), render, TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), render,
"text", COL_TEXT, NULL);
- g_signal_connect(combo, "changed", G_CALLBACK(cb_dev_selected),
- GINT_TO_POINTER(type));
- g_signal_connect(check, "toggled", G_CALLBACK(cb_toggle_enabled), data);
+ gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE);
+ update_volume_slider(slider, type);
+
+ struct device_controls_cb_data *cb_data = g_new(struct device_controls_cb_data, 1);
+ cb_data->combo = combo;
+ cb_data->slider = slider;
+ cb_data->type = type;
+
+ g_signal_connect(combo, "changed",
+ G_CALLBACK(cb_dev_selected), GINT_TO_POINTER(type));
+ g_signal_connect(check, "toggled",
+ G_CALLBACK(cb_toggle_enabled), cb_data);
+ g_signal_connect(slider, "button-release-event",
+ G_CALLBACK(cb_volume_set), GINT_TO_POINTER(type));
}
@@ -254,8 +336,8 @@ static void
cb_init(GtkApplication* app, gpointer user_data)
{
GtkWidget *window, *vbox_main,
- *hbox_play, *combo_play, *check_play,
- *hbox_rec, *combo_rec, *check_rec;
+ *hbox_play, *combo_play, *check_play, *slider_play,
+ *hbox_rec, *combo_rec, *check_rec, *slider_rec;
GtkListStore *store_play, *store_rec;
(void)user_data;
@@ -270,12 +352,18 @@ cb_init(GtkApplication* app, gpointer user_data)
store_play = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
combo_play = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store_play));
check_play = gtk_check_button_new_with_label("Disabled");
- setup_device_selection(store_play, combo_play, check_play, DEVTYPE_PLAY);
+ slider_play = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,
+ 0.0, 100.0, 1.0);
+ setup_device_controls(store_play, combo_play, check_play,
+ slider_play, DEVTYPE_PLAY);
store_rec = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
combo_rec = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store_rec));
check_rec = gtk_check_button_new_with_label("Disabled");
- setup_device_selection(store_rec, combo_rec, check_rec, DEVTYPE_REC);
+ slider_rec = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,
+ 0.0, 100.0, 1.0);
+ setup_device_controls(store_rec, combo_rec, check_rec,
+ slider_rec, DEVTYPE_REC);
hbox_play = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_pack_start(GTK_BOX(hbox_play), combo_play, TRUE, TRUE, 0);
@@ -287,7 +375,9 @@ cb_init(GtkApplication* app, gpointer user_data)
vbox_main = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
gtk_box_pack_start(GTK_BOX(vbox_main), hbox_play, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox_main), slider_play, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox_main), hbox_rec, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox_main), slider_rec, FALSE, FALSE, 0);
gtk_widget_set_margin_start(vbox_main, 12);
gtk_widget_set_margin_end(vbox_main, 12);