chiark / gitweb /
eclient integer callbacks now get errors instead of using generic
[disorder] / disobedience / queue.c
index 73b49abe8bc6e3c84ec7050ac1fb81151c9abd26..c3d62b00a8fc9a9bcd559dcfcba1253e3cdcfaac 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder
- * Copyright (C) 2006,  2007 Richard Kettlewell
+ * Copyright (C) 2006-2008 Richard Kettlewell
  *
  * 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
@@ -272,36 +272,33 @@ static void namepart_completed_or_failed(void) {
   }
 }
 
-/** @brief Called when A namepart lookup has completed */
-static void namepart_completed(void *v, const char *value) {
-  struct callbackdata *cbd = v;
+/** @brief Called when a namepart lookup has completed */
+static void namepart_completed(void *v, const char *error, const char *value) {
+  if(error) {
+    gtk_label_set_text(GTK_LABEL(report_label), error);
+  } else {
+    const char *key = v;
 
-  D(("namepart_completed"));
-  cache_put(&cachetype_string, cbd->u.key, value);
-  ++namepart_completions_deferred;
+    cache_put(&cachetype_string, key, value);
+    ++namepart_completions_deferred;
+  }
   namepart_completed_or_failed();
 }
 
 /** @brief Called when a length lookup has completed */
-static void length_completed(void *v, long l) {
-  struct callbackdata *cbd = v;
-  long *value;
-
-  D(("namepart_completed"));
-  value = xmalloc(sizeof *value);
-  *value = l;
-  cache_put(&cachetype_integer, cbd->u.key, value);
-  ++namepart_completions_deferred;
-  namepart_completed_or_failed();
-}
-
-/** @brief Called when a length or namepart lookup has failed */
-static void namepart_protocol_error(
-  struct callbackdata attribute((unused)) *cbd,
-  int attribute((unused)) code,
-  const char *msg) {
-  D(("namepart_protocol_error"));
-  gtk_label_set_text(GTK_LABEL(report_label), msg);
+static void length_completed(void *v, const char *error, long l) {
+  if(error)
+    gtk_label_set_text(GTK_LABEL(report_label), error);
+  else {
+    const char *key = v;
+    long *value;
+    
+    D(("namepart_completed"));
+    value = xmalloc(sizeof *value);
+    *value = l;
+    cache_put(&cachetype_integer, key, value);
+    ++namepart_completions_deferred;
+  }
   namepart_completed_or_failed();
 }
 
@@ -310,14 +307,9 @@ static void namepart_fill(const char *track,
                           const char *context,
                           const char *part,
                           const char *key) {
-  struct callbackdata *cbd;
-
   ++namepart_lookups_outstanding;
-  cbd = xmalloc(sizeof *cbd);
-  cbd->onerror = namepart_protocol_error;
-  cbd->u.key = key;
   disorder_eclient_namepart(client, namepart_completed,
-                            track, context, part, cbd);
+                            track, context, part, (void *)key);
 }
 
 /** @brief Look up a namepart
@@ -364,7 +356,6 @@ void namepart_update(const char *track,
 static long getlength(const char *track) {
   char *key;
   const long *value;
-  struct callbackdata *cbd;
   static const long bogus = -1;
 
   D(("getlength %s", track));
@@ -374,10 +365,7 @@ static long getlength(const char *track) {
     D(("deferring..."));;
     cache_put(&cachetype_integer, key, value = &bogus);
     ++namepart_lookups_outstanding;
-    cbd = xmalloc(sizeof *cbd);
-    cbd->onerror = namepart_protocol_error;
-    cbd->u.key = key;
-    disorder_eclient_length(client, length_completed, track, cbd);
+    disorder_eclient_length(client, length_completed, track, key);
   }
   return *value;
 }
@@ -703,6 +691,16 @@ void queue_select_all(struct queuelike *ql) {
   set_widget_states(ql);
 }
 
+/** @brief Deselect all entries in a queue */
+void queue_select_none(struct queuelike *ql) {
+  struct queue_entry *qq;
+
+  for(qq = ql->q; qq; qq = qq->next)
+    selection_set(ql->selection, qq->id, 0);
+  ql->last_click = 0;
+  set_widget_states(ql);
+}
+
 /** @brief Pop up properties for selected tracks */
 void queue_properties(struct queuelike *ql) {
   struct vector v;
@@ -768,6 +766,12 @@ static struct queue_entry *findentry(struct queuelike *ql,
   return q;
 }
 
+static void move_completed(void attribute((unused)) *v,
+                           const char *error) {
+  if(error)
+    popup_protocol_error(0, error);
+}
+
 /** @brief Called when data is dropped */
 static gboolean queue_drag_drop(GtkWidget attribute((unused)) *widget,
                                 GdkDragContext *drag_context,
@@ -787,7 +791,7 @@ static gboolean queue_drag_drop(GtkWidget attribute((unused)) *widget,
     if(q != playing_track && selection_selected(ql->selection, q->id))
       vector_append(&vec, (char *)q->id);
   disorder_eclient_moveafter(client, id, vec.nvec, (const char **)vec.vec,
-                             0/*completed*/, 0/*v*/);
+                             move_completed, 0/*v*/);
   gtk_drag_finish(drag_context, TRUE, TRUE, when);
   /* Destroy dropzones */
   remove_drag_targets(ql);
@@ -1184,11 +1188,18 @@ static int scratch_sensitive(struct queuelike attribute((unused)) *ql,
           && selection_selected(ql->selection, playing_track->id));
 }
 
+/** @brief Called when disorder_eclient_scratch completes */
+static void scratch_completed(void attribute((unused)) *v,
+                              const char *error) {
+  if(error)
+    popup_protocol_error(0, error);
+}
+
 /** @brief Scratch the playing track */
 static void scratch_activate(GtkMenuItem attribute((unused)) *menuitem,
                              gpointer attribute((unused)) user_data) {
   if(playing_track)
-    disorder_eclient_scratch(client, playing_track->id, 0, 0);
+    disorder_eclient_scratch(client, playing_track->id, scratch_completed, 0);
 }
 
 /** @brief Determine whether the remove option should be sensitive */
@@ -1203,6 +1214,12 @@ static int remove_sensitive(struct queuelike *ql,
               || count_selected_nonplaying(ql)));
 }
 
+static void remove_completed(void attribute((unused)) *v,
+                             const char *error) {
+  if(error)
+    popup_protocol_error(0, error);
+}
+
 /** @brief Remove selected track(s) */
 static void remove_activate(GtkMenuItem attribute((unused)) *menuitem,
                             gpointer user_data) {
@@ -1214,10 +1231,10 @@ static void remove_activate(GtkMenuItem attribute((unused)) *menuitem,
     /* Remove selected tracks */
     for(q = ql->q; q; q = q->next)
       if(selection_selected(ql->selection, q->id) && q != playing_track)
-        disorder_eclient_remove(client, q->id, 0, 0);
+        disorder_eclient_remove(client, q->id, move_completed, 0);
   } else if(q)
     /* Remove just the hovered track */
-    disorder_eclient_remove(client, q->id, 0, 0);
+    disorder_eclient_remove(client, q->id, remove_completed, 0);
 }
 
 /** @brief Determine whether the properties menu option should be sensitive */
@@ -1252,6 +1269,21 @@ static void selectall_activate(GtkMenuItem attribute((unused)) *menuitem,
   queue_select_all(mii->ql);
 }
 
+/** @brief Determine whether the select none menu option should be sensitive */
+static int selectnone_sensitive(struct queuelike *ql,
+                                struct queue_menuitem attribute((unused)) *m,
+                                struct queue_entry attribute((unused)) *q) {
+  /* Sensitive if there is anything selected */
+  return hash_count(ql->selection) != 0;
+}
+
+/** @brief Select no tracks */
+static void selectnone_activate(GtkMenuItem attribute((unused)) *menuitem,
+                               gpointer user_data) {
+  const struct menuiteminfo *mii = user_data;
+  queue_select_none(mii->ql);
+}
+
 /** @brief Determine whether the play menu option should be sensitive */
 static int play_sensitive(struct queuelike *ql,
                           struct queue_menuitem attribute((unused)) *m,
@@ -1272,10 +1304,10 @@ static void play_activate(GtkMenuItem attribute((unused)) *menuitem,
     /* Play selected tracks */
     for(q = ql->q; q; q = q->next)
       if(selection_selected(ql->selection, q->id))
-        disorder_eclient_play(client, q->track, 0, 0);
+        disorder_eclient_play(client, q->track, play_completed, 0);
   } else if(q)
     /* Nothing is selected, so play the hovered track */
-    disorder_eclient_play(client, q->track, 0, 0);
+    disorder_eclient_play(client, q->track, play_completed, 0);
 }
 
 /* The queue --------------------------------------------------------------- */
@@ -1311,6 +1343,7 @@ static gboolean adjust_sofar(gpointer attribute((unused)) data) {
 static struct queue_menuitem queue_menu[] = {
   { "Track properties", properties_activate, properties_sensitive, 0, 0 },
   { "Select all tracks", selectall_activate, selectall_sensitive, 0, 0 },
+  { "Deselect all tracks", selectnone_activate, selectnone_sensitive, 0, 0 },
   { "Scratch track", scratch_activate, scratch_sensitive, 0, 0 },
   { "Remove track from queue", remove_activate, remove_sensitive, 0, 0 },
   { 0, 0, 0, 0, 0 }
@@ -1383,6 +1416,7 @@ static struct queue_entry *fixup_recent(struct queue_entry *q) {
 static struct queue_menuitem recent_menu[] = {
   { "Track properties", properties_activate, properties_sensitive,0, 0 },
   { "Select all tracks", selectall_activate, selectall_sensitive, 0, 0 },
+  { "Deselect all tracks", selectnone_activate, selectnone_sensitive, 0, 0 },
   { 0, 0, 0, 0, 0 }
 };
 
@@ -1416,6 +1450,7 @@ static struct queue_menuitem added_menu[] = {
   { "Track properties", properties_activate, properties_sensitive, 0, 0 },
   { "Play track", play_activate, play_sensitive, 0, 0 },
   { "Select all tracks", selectall_activate, selectall_sensitive, 0, 0 },
+  { "Deselect all tracks", selectnone_activate, selectnone_sensitive, 0, 0 },
   { 0, 0, 0, 0, 0 }
 };
 
@@ -1474,6 +1509,12 @@ static int queue_selectall_sensitive(GtkWidget *w) {
   return !!queue_count_entries(g_object_get_data(G_OBJECT(w), "queue"));
 }
 
+static int queue_selectnone_sensitive(GtkWidget *w) {
+  struct queuelike *const ql = g_object_get_data(G_OBJECT(w), "queue");
+
+  return hash_count(ql->selection) != 0;
+}
+
 static void queue_properties_activate(GtkWidget *w) {
   queue_properties(g_object_get_data(G_OBJECT(w), "queue"));
 }
@@ -1482,11 +1523,17 @@ static void queue_selectall_activate(GtkWidget *w) {
   queue_select_all(g_object_get_data(G_OBJECT(w), "queue"));
 }
 
+static void queue_selectnone_activate(GtkWidget *w) {
+  queue_select_none(g_object_get_data(G_OBJECT(w), "queue"));
+}
+
 static const struct tabtype tabtype_queue = {
   queue_properties_sensitive,
   queue_selectall_sensitive,
+  queue_selectnone_sensitive,
   queue_properties_activate,
   queue_selectall_activate,
+  queue_selectnone_activate,
 };
 
 /* Other entry points ------------------------------------------------------ */