chiark / gitweb /
update control buttons directly from state bits
authorRichard Kettlewell <rjk@greenend.org.uk>
Sun, 30 Sep 2007 22:01:14 +0000 (23:01 +0100)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sun, 30 Sep 2007 22:01:14 +0000 (23:01 +0100)
disobedience/control.c
disobedience/disobedience.h
disobedience/log.c
lib/eclient.c
lib/eclient.h

index fb42801..cb2d63c 100644 (file)
@@ -51,6 +51,8 @@ static void volume_adjusted(GtkAdjustment *a, gpointer user_data);
 static gchar *format_volume(GtkScale *scale, gdouble value);
 static gchar *format_balance(GtkScale *scale, gdouble value);
 
+static void control_monitor(void *u);
+
 /* Control bar ------------------------------------------------------------- */
 
 static int suppress_set_volume;
@@ -152,27 +154,35 @@ GtkWidget *control_widget(void) {
                    G_CALLBACK(format_volume), 0);
   g_signal_connect(G_OBJECT(b), "format-value",
                    G_CALLBACK(format_balance), 0);
+  register_monitor(control_monitor, 0, -1UL);
   return hbox;
 }
 
 /** @brief Update the control bar after some kind of state change */
 void control_update(void) {
-  int n;
   double l, r;
 
   D(("control_update"));
-  for(n = 0; n < NICONS; ++n)
-    icons[n].update(&icons[n]);
+  /*control_monitor(0, disorder_eclient_state(client));*/
   l = volume_l / 100.0;
   r = volume_r / 100.0;
-  ++suppress_set_volume;;
+  ++suppress_set_volume;
   gtk_adjustment_set_value(volume_adj, volume(l, r) * goesupto);
   gtk_adjustment_set_value(balance_adj, balance(l, r));
   --suppress_set_volume;
 }
 
+static void control_monitor(void attribute((unused)) *u) {
+  int n;
+
+  fprintf(stderr, "control_monitor\n");
+  for(n = 0; n < NICONS; ++n)
+    icons[n].update(&icons[n]);
+  fprintf(stderr, "\n");
+}
+
 /** @brief Update the state of one of the control icons
- * @param button Widget for button
+ * @param icon Target icon
  * @param visible True if this version of the button should be visible
  * @param usable True if the button is currently usable
  *
@@ -183,57 +193,58 @@ void control_update(void) {
  * @p usable need not take into account server availability, that is done
  * automatically.
  */
-static void update_icon(GtkWidget *button, 
+static void update_icon(const struct icon *icon,
                         int visible, int usable) {
   /* If the connection is down nothing is ever usable */
-  if(!(disorder_eclient_state(client) & DISORDER_CONNECTED))
+  if(!(last_state & DISORDER_CONNECTED))
     usable = 0;
-  (visible ? gtk_widget_show : gtk_widget_hide)(button);
+  fprintf(stderr, "%s usable=%d visible=%d\n", icon->tip, usable, visible);
+  (visible ? gtk_widget_show : gtk_widget_hide)(icon->button);
   /* Only both updating usability if the button is visible */
   if(visible)
-    gtk_widget_set_sensitive(button, usable);
+    gtk_widget_set_sensitive(icon->button, usable);
 }
 
 static void update_pause(const struct icon *icon) {
-  int visible = !(last_state & DISORDER_TRACK_PAUSED);
-  int usable = playing;                 /* TODO: might be a lie */
-  update_icon(icon->button, visible, usable);
+  const int visible = !(last_state & DISORDER_TRACK_PAUSED);
+  const int usable = !!(last_state & DISORDER_PLAYING); /* TODO: might be a lie */
+  update_icon(icon, visible, usable);
 }
 
 static void update_play(const struct icon *icon) {
-  int visible = !!(last_state & DISORDER_TRACK_PAUSED);
-  int usable = playing;
-  update_icon(icon->button, visible, usable);
+  const int visible = !!(last_state & DISORDER_TRACK_PAUSED);
+  const int usable = !!(last_state & DISORDER_PLAYING);
+  update_icon(icon, visible, usable);
 }
 
 static void update_scratch(const struct icon *icon) {
-  int visible = 1;
-  int usable = playing;
-  update_icon(icon->button, visible, usable);
+  const int visible = 1;
+  const int usable = !!(last_state & DISORDER_PLAYING);
+  update_icon(icon, visible, usable);
 }
 
 static void update_random_enable(const struct icon *icon) {
-  int visible = !(last_state & DISORDER_RANDOM_ENABLED);
-  int usable = 1;
-  update_icon(icon->button, visible, usable);
+  const int visible = !(last_state & DISORDER_RANDOM_ENABLED);
+  const int usable = 1;
+  update_icon(icon, visible, usable);
 }
 
 static void update_random_disable(const struct icon *icon) {
-  int visible = !!(last_state & DISORDER_RANDOM_ENABLED);
-  int usable = 1;
-  update_icon(icon->button, visible, usable);
+  const int visible = !!(last_state & DISORDER_RANDOM_ENABLED);
+  const int usable = 1;
+  update_icon(icon, visible, usable);
 }
 
 static void update_enable(const struct icon *icon) {
-  int visible = !(last_state & DISORDER_PLAYING_ENABLED);
-  int usable = 1;
-  update_icon(icon->button, visible, usable);
+  const int visible = !(last_state & DISORDER_PLAYING_ENABLED);
+  const int usable = 1;
+  update_icon(icon, visible, usable);
 }
 
 static void update_disable(const struct icon *icon) {
-  int visible = !!(last_state & DISORDER_PLAYING_ENABLED);
-  int usable = 1;
-  update_icon(icon->button, visible, usable);
+  const int visible = !!(last_state & DISORDER_PLAYING_ENABLED);
+  const int usable = 1;
+  update_icon(icon, visible, usable);
 }
 
 static void clicked_icon(GtkButton attribute((unused)) *button,
index 7449e27..6727ba2 100644 (file)
@@ -91,7 +91,7 @@ extern int choosealpha;                 /* break up choose by letter */
 
 extern const disorder_eclient_log_callbacks log_callbacks;
 
-typedef void monitor_callback(void *u, unsigned long newstate);
+typedef void monitor_callback(void *u);
 
 /* Functions --------------------------------------------------------------- */
 
index e170c2a..943c5e3 100644 (file)
@@ -142,14 +142,15 @@ static void log_scratched(void attribute((unused)) *v,
 static void log_state(void attribute((unused)) *v,
                       unsigned long state) {
   const struct monitor *m;
+  const unsigned long changes = state ^ last_state;
 
+  info("log_state %s", disorder_eclient_interpret_state(state));
+  last_state = state;
   /* Tell anything that cares about the state change */
   for(m = monitors; m; m = m->next) {
-    if((state ^ last_state) & m->mask)
-      m->callback(m->u, state);
+    if(changes & m->mask)
+      m->callback(m->u);
   }
-  last_state = state;
-  control_update();
   /* If the track is paused or resume then the currently playing track is
    * refetched so that we can continue to correctly calculate the played so-far
    * field */
index 2ff4ce4..970b9ab 100644 (file)
@@ -1178,7 +1178,7 @@ static void logline(disorder_eclient *c, const char *line) {
   char **vec;
   uintmax_t when;
 
-  D(("log_opcallback [%s]", line));
+  info("log_opcallback [%s]", line);
   vec = split(line, &nvec, SPLIT_QUOTES, logline_error, c);
   if(nvec < 2) return;                  /* probably an error, already
                                          * reported */
@@ -1313,6 +1313,43 @@ static void logentry_volume(disorder_eclient *c,
   c->log_callbacks->volume(c->log_v, (int)l, (int)r);
 }
 
+/** @brief Convert @p statebits to a string */
+char *disorder_eclient_interpret_state(unsigned long statebits) {
+  struct dynstr d[1];
+  size_t n;
+
+  static const struct {
+    unsigned long bit;
+    const char *name;
+  } bits[] = {
+    { DISORDER_PLAYING_ENABLED, "playing_enabled" },
+    { DISORDER_RANDOM_ENABLED, "random_enabled" },
+    { DISORDER_TRACK_PAUSED, "track_paused" },
+    { DISORDER_PLAYING, "playing" },
+    { DISORDER_CONNECTED, "connected" },
+  };
+#define NBITS (sizeof bits / sizeof *bits)
+
+  dynstr_init(d);
+  for(n = 0; n < NBITS; ++n)
+    if(statebits & bits[n].bit) {
+      if(d->nvec)
+        dynstr_append(d, '|');
+      dynstr_append_string(d, bits[n].name);
+      statebits ^= bits[n].bit;
+    }
+  if(statebits) {
+    char s[20];
+
+    if(d->nvec)
+      dynstr_append(d, '|');
+    sprintf(s, "%#lx", statebits);
+    dynstr_append_string(d, s);
+  }
+  dynstr_terminate(d);
+  return d->vec;
+}
+
 /*
 Local Variables:
 c-basic-offset:2
index 6fdb386..ba81375 100644 (file)
@@ -127,6 +127,8 @@ typedef struct disorder_eclient_log_callbacks {
  */
 #define DISORDER_CONNECTED        0x00000010
 
+char *disorder_eclient_interpret_state(unsigned long statebits);
+
 struct queue_entry;
 struct kvp;
 struct sink;