X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/d4ef413201b6aa149d11992dc2527e07cd9085d4..e84ca2905e0e8d75dbeb53d0001b414ba956a8a6:/disobedience/control.c diff --git a/disobedience/control.c b/disobedience/control.c index 92e2b74..57931be 100644 --- a/disobedience/control.c +++ b/disobedience/control.c @@ -22,6 +22,7 @@ */ #include "disobedience.h" +#include "mixer.h" /* Forward declarations ---------------------------------------------------- */ @@ -66,8 +67,8 @@ static gchar *format_balance(GtkScale *scale, gdouble value); /* Control bar ------------------------------------------------------------- */ -/** @brief Guard against feedback loop in volume control */ -static int suppress_set_volume; +/** @brief Guard against feedback */ +int suppress_actions = 1; /** @brief Definition of an icon * @@ -207,22 +208,30 @@ static struct icon icons[] = { static GtkAdjustment *volume_adj; static GtkAdjustment *balance_adj; +static GtkWidget *volume_widget; +static GtkWidget *balance_widget; /** @brief Called whenever last_state changes in any way */ void control_monitor(void attribute((unused)) *u) { int n; + gboolean volume_supported; D(("control_monitor")); for(n = 0; n < NICONS; ++n) icons[n].update(&icons[n]); + /* Only display volume/balance controls if they will work */ + if(!rtp_supported + || (rtp_supported && mixer_supported(DEFAULT_BACKEND))) + volume_supported = TRUE; + else + volume_supported = FALSE; + (volume_supported ? gtk_widget_show : gtk_widget_hide)(volume_widget); + (volume_supported ? gtk_widget_show : gtk_widget_hide)(balance_widget); } /** @brief Create the control bar */ GtkWidget *control_widget(void) { GtkWidget *hbox = gtk_hbox_new(FALSE, 1), *vbox; - GtkWidget *content; - GdkPixbuf *pb; - GtkWidget *v, *b; int n; NW(hbox); @@ -230,20 +239,7 @@ GtkWidget *control_widget(void) { assert(mainmenufactory); /* ordering must be right */ for(n = 0; n < NICONS; ++n) { NW(button); - icons[n].button = gtk_button_new(); - gtk_widget_modify_bg(icons[n].button, GTK_STATE_NORMAL, &tool_bg); - gtk_widget_modify_bg(icons[n].button, GTK_STATE_ACTIVE, &tool_active); - gtk_widget_modify_bg(icons[n].button, GTK_STATE_PRELIGHT, &tool_active); - gtk_widget_modify_bg(icons[n].button, GTK_STATE_SELECTED, &tool_active); - if((pb = find_image(icons[n].icon))) { - NW(image); - content = gtk_image_new_from_pixbuf(pb); - } else { - NW(label); - content = gtk_label_new(icons[n].icon); - } - gtk_container_add(GTK_CONTAINER(icons[n].button), content); - gtk_tooltips_set_tip(tips, icons[n].button, icons[n].tip, ""); + icons[n].button = iconbutton(icons[n].icon, icons[n].tip); g_signal_connect(G_OBJECT(icons[n].button), "clicked", G_CALLBACK(clicked_icon), &icons[n]); /* pop the icon in a vbox so it doesn't get vertically stretch if there are @@ -280,31 +276,31 @@ GtkWidget *control_widget(void) { 0.2, 0.2, 0)); /* the volume control */ NW(hscale); - v = gtk_hscale_new(volume_adj); + volume_widget = gtk_hscale_new(volume_adj); NW(hscale); - b = gtk_hscale_new(balance_adj); - set_slider_colors(v); - set_slider_colors(b); - gtk_scale_set_digits(GTK_SCALE(v), 10); - gtk_scale_set_digits(GTK_SCALE(b), 10); - gtk_widget_set_size_request(v, 192, -1); - gtk_widget_set_size_request(b, 192, -1); - gtk_tooltips_set_tip(tips, v, "Volume", ""); - gtk_tooltips_set_tip(tips, b, "Balance", ""); - gtk_box_pack_start(GTK_BOX(hbox), v, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), b, FALSE, TRUE, 0); + balance_widget = gtk_hscale_new(balance_adj); + gtk_widget_set_style(volume_widget, tool_style); + gtk_widget_set_style(balance_widget, tool_style); + gtk_scale_set_digits(GTK_SCALE(volume_widget), 10); + gtk_scale_set_digits(GTK_SCALE(balance_widget), 10); + gtk_widget_set_size_request(volume_widget, 192, -1); + gtk_widget_set_size_request(balance_widget, 192, -1); + gtk_tooltips_set_tip(tips, volume_widget, "Volume", ""); + gtk_tooltips_set_tip(tips, balance_widget, "Balance", ""); + gtk_box_pack_start(GTK_BOX(hbox), volume_widget, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(hbox), balance_widget, FALSE, TRUE, 0); /* space updates rather than hammering the server */ - gtk_range_set_update_policy(GTK_RANGE(v), GTK_UPDATE_DELAYED); - gtk_range_set_update_policy(GTK_RANGE(b), GTK_UPDATE_DELAYED); + gtk_range_set_update_policy(GTK_RANGE(volume_widget), GTK_UPDATE_DELAYED); + gtk_range_set_update_policy(GTK_RANGE(balance_widget), GTK_UPDATE_DELAYED); /* notice when the adjustments are changed */ g_signal_connect(G_OBJECT(volume_adj), "value-changed", G_CALLBACK(volume_adjusted), 0); g_signal_connect(G_OBJECT(balance_adj), "value-changed", G_CALLBACK(volume_adjusted), 0); /* format the volume/balance values ourselves */ - g_signal_connect(G_OBJECT(v), "format-value", + g_signal_connect(G_OBJECT(volume_widget), "format-value", G_CALLBACK(format_volume), 0); - g_signal_connect(G_OBJECT(b), "format-value", + g_signal_connect(G_OBJECT(balance_widget), "format-value", G_CALLBACK(format_balance), 0); register_monitor(control_monitor, 0, -1UL); return hbox; @@ -317,10 +313,10 @@ void volume_update(void) { D(("volume_update")); l = volume_l / 100.0; r = volume_r / 100.0; - ++suppress_set_volume; + ++suppress_actions; gtk_adjustment_set_value(volume_adj, volume(l, r) * goesupto); gtk_adjustment_set_value(balance_adj, balance(l, r)); - --suppress_set_volume; + --suppress_actions; } /** @brief Update the state of one of the control icons @@ -413,14 +409,16 @@ static void clicked_icon(GtkButton attribute((unused)) *button, gpointer userdata) { const struct icon *icon = userdata; - icon->action(client, 0, 0); + if(!suppress_actions) + icon->action(client, 0, 0); } static void clicked_menu(GtkMenuItem attribute((unused)) *menuitem, gpointer userdata) { const struct icon *icon = userdata; - icon->action(client, 0, 0); + if(!suppress_actions) + icon->action(client, 0, 0); } static void toggled_menu(GtkCheckMenuItem *menuitem, @@ -428,6 +426,8 @@ static void toggled_menu(GtkCheckMenuItem *menuitem, const struct icon *icon = userdata; size_t n; + if(suppress_actions) + return; /* This is a bit fiddlier than the others, we need to find the action for the * new state. If the new state is active then we want the ICON_INACTIVE * version and vica versa. */ @@ -445,7 +445,7 @@ static void volume_adjusted(GtkAdjustment attribute((unused)) *a, double v = gtk_adjustment_get_value(volume_adj) / goesupto; double b = gtk_adjustment_get_value(balance_adj); - if(suppress_set_volume) + if(suppress_actions) /* This is the result of an update from the server, not a change from the * user. Don't feedback! */ return; @@ -455,10 +455,15 @@ static void volume_adjusted(GtkAdjustment attribute((unused)) *a, b = nearbyint(5 * b) / 5; /* Set the volume. We don't want a reply, we'll get the actual new volume * from the log. */ - disorder_eclient_volume(client, 0, - nearbyint(left(v, b) * 100), - nearbyint(right(v, b) * 100), - 0); + if(rtp_supported) { + int l = nearbyint(left(v, b) * 100), r = nearbyint(right(v, b) * 100); + mixer_control(DEFAULT_BACKEND, &l, &r, 1); + } else + /* We don't want a reply, we'll get the actual new volume from the log. */ + disorder_eclient_volume(client, 0, + nearbyint(left(v, b) * 100), + nearbyint(right(v, b) * 100), + 0); } /** @brief Formats the volume value */