chiark / gitweb /
rearrange code so more of it happens forwards
authorRichard Kettlewell <rjk@greenend.org.uk>
Mon, 23 Nov 2009 17:15:50 +0000 (17:15 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Mon, 23 Nov 2009 17:15:50 +0000 (17:15 +0000)
disobedience/playlists.c

index 2673e1c526ddb325ab6ced81a212790dc6a00a35..0785bbeecb912d09cfdfbf9d981ae87dc2a0e76f 100644 (file)
@@ -54,6 +54,38 @@ static void playlist_playall_activate(GtkMenuItem *menuitem,
 static int playlist_remove_sensitive(void *extra) ;
 static void playlist_remove_activate(GtkMenuItem *menuitem,
                                      gpointer user_data);
 static int playlist_remove_sensitive(void *extra) ;
 static void playlist_remove_activate(GtkMenuItem *menuitem,
                                      gpointer user_data);
+static void playlist_new_locked(void *v, const char *err);
+static void playlist_new_retrieved(void *v, const char *err,
+                                   int nvec,
+                                   char **vec);
+static void playlist_new_created(void *v, const char *err);
+static void playlist_new_unlocked(void *v, const char *err);
+static void playlist_new_entry_edited(GtkEditable *editable,
+                                      gpointer user_data);
+static void playlist_new_button_toggled(GtkToggleButton *tb,
+                                        gpointer userdata);
+static void playlist_new_changed(const char *event,
+                                 void *eventdata,
+                                 void *callbackdata);
+static const char *playlist_new_valid(void);
+static void playlist_new_details(char **namep,
+                                 char **fullnamep,
+                                 gboolean *sharedp,
+                                 gboolean *publicp,
+                                 gboolean *privatep);
+static void playlist_new_ok(GtkButton *button,
+                            gpointer userdata);
+static void playlist_new_cancel(GtkButton *button,
+                                gpointer userdata);
+static void playlists_editor_received_tracks(void *v,
+                                             const char *err,
+                                             int nvec, char **vec);
+static void playlist_window_destroyed(GtkWidget *widget,
+                                      GtkWidget **widget_pointer);
+static gboolean playlist_window_keypress(GtkWidget *widget,
+                                         GdkEventKey *event,
+                                         gpointer user_data);
+static int playlistcmp(const void *ap, const void *bp);
 
 /** @brief Playlist editing window */
 static GtkWidget *playlist_window;
 
 /** @brief Playlist editing window */
 static GtkWidget *playlist_window;
@@ -111,6 +143,23 @@ static void playlist_list_update(const char attribute((unused)) *event,
   disorder_eclient_playlists(client, playlist_list_received_playlists, 0);
 }
 
   disorder_eclient_playlists(client, playlist_list_received_playlists, 0);
 }
 
+/** @brief Called with a new list of playlists */
+static void playlist_list_received_playlists(void attribute((unused)) *v,
+                                             const char *err,
+                                             int nvec, char **vec) {
+  if(err) {
+    playlists = 0;
+    nplaylists = -1;
+    /* Probably means server does not support playlists */
+  } else {
+    playlists = vec;
+    nplaylists = nvec;
+    qsort(playlists, nplaylists, sizeof (char *), playlistcmp);
+  }
+  /* Tell our consumers */
+  event_raise("playlists-updated", 0);
+}
+
 /** @brief qsort() callback for playlist name comparison */
 static int playlistcmp(const void *ap, const void *bp) {
   const char *a = *(char **)ap, *b = *(char **)bp;
 /** @brief qsort() callback for playlist name comparison */
 static int playlistcmp(const void *ap, const void *bp) {
   const char *a = *(char **)ap, *b = *(char **)bp;
@@ -137,23 +186,6 @@ static int playlistcmp(const void *ap, const void *bp) {
   return strcmp(a, b);
 }
 
   return strcmp(a, b);
 }
 
-/** @brief Called with a new list of playlists */
-static void playlist_list_received_playlists(void attribute((unused)) *v,
-                                             const char *err,
-                                             int nvec, char **vec) {
-  if(err) {
-    playlists = 0;
-    nplaylists = -1;
-    /* Probably means server does not support playlists */
-  } else {
-    playlists = vec;
-    nplaylists = nvec;
-    qsort(playlists, nplaylists, sizeof (char *), playlistcmp);
-  }
-  /* Tell our consumers */
-  event_raise("playlists-updated", 0);
-}
-
 /* Playlists menu ----------------------------------------------------------- */
 
 static void playlist_menu_playing(void attribute((unused)) *v,
 /* Playlists menu ----------------------------------------------------------- */
 
 static void playlist_menu_playing(void attribute((unused)) *v,
@@ -236,52 +268,117 @@ static GtkWidget *playlist_new_public;
 /** @brief "Private" radio button */
 static GtkWidget *playlist_new_private;
 
 /** @brief "Private" radio button */
 static GtkWidget *playlist_new_private;
 
-/** @brief Get entered new-playlist details
- * @param namep Where to store entered name (or NULL)
- * @param fullnamep Where to store computed full name (or NULL)
- * @param sharep Where to store 'shared' flag (or NULL)
- * @param publicp Where to store 'public' flag (or NULL)
- * @param privatep Where to store 'private' flag (or NULL)
- */
-static void playlist_new_details(char **namep,
-                                 char **fullnamep,
-                                 gboolean *sharedp,
-                                 gboolean *publicp,
-                                 gboolean *privatep) {
-  gboolean shared, public, private;
-  g_object_get(playlist_new_shared, "active", &shared, (char *)NULL);
-  g_object_get(playlist_new_public, "active", &public, (char *)NULL);
-  g_object_get(playlist_new_private, "active", &private, (char *)NULL);
-  char *gname = gtk_editable_get_chars(GTK_EDITABLE(playlist_new_entry),
-                                       0, -1); /* name owned by calle */
-  char *name = xstrdup(gname);
-  g_free(gname);
-  if(sharedp) *sharedp = shared;
-  if(publicp) *publicp = public;
-  if(privatep) *privatep = private;
-  if(namep) *namep = name;
-  if(fullnamep) {
-    if(*sharedp) *fullnamep = *namep;
-    else byte_xasprintf(fullnamep, "%s.%s", config->username, name);
+/** @brief Buttons for new-playlist popup */
+static struct button playlist_new_buttons[] = {
+  {
+    .stock = GTK_STOCK_OK,
+    .clicked = playlist_new_ok,
+    .tip = "Create new playlist"
+  },
+  {
+    .stock = GTK_STOCK_CANCEL,
+    .clicked = playlist_new_cancel,
+    .tip = "Do not create new playlist"
   }
   }
+};
+#define NPLAYLIST_NEW_BUTTONS (sizeof playlist_new_buttons / sizeof *playlist_new_buttons)
+
+/** @brief Pop up a new window to enter the playlist name and details */
+static void playlist_new_playlist(void) {
+  assert(playlist_new_window == NULL);
+  playlist_new_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  g_signal_connect(playlist_new_window, "destroy",
+                  G_CALLBACK(gtk_widget_destroyed), &playlist_new_window);
+  gtk_window_set_title(GTK_WINDOW(playlist_new_window), "Create new playlist");
+  /* Window will be modal, suppressing access to other windows */
+  gtk_window_set_modal(GTK_WINDOW(playlist_new_window), TRUE);
+  gtk_window_set_transient_for(GTK_WINDOW(playlist_new_window),
+                               GTK_WINDOW(playlist_window));
+
+  /* Window contents will use a table (grid) layout */
+  GtkWidget *table = gtk_table_new(3, 3, FALSE/*!homogeneous*/);
+
+  /* First row: playlist name */
+  gtk_table_attach_defaults(GTK_TABLE(table),
+                            gtk_label_new("Playlist name"),
+                            0, 1, 0, 1);
+  playlist_new_entry = gtk_entry_new();
+  g_signal_connect(playlist_new_entry, "changed",
+                   G_CALLBACK(playlist_new_entry_edited), NULL);
+  gtk_table_attach_defaults(GTK_TABLE(table),
+                            playlist_new_entry,
+                            1, 3, 0, 1);
+
+  /* Second row: radio buttons to choose type */
+  playlist_new_shared = gtk_radio_button_new_with_label(NULL, "shared");
+  playlist_new_public
+    = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(playlist_new_shared),
+                                                  "public");
+  playlist_new_private
+    = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(playlist_new_shared),
+                                                  "private");
+  g_signal_connect(playlist_new_shared, "toggled",
+                   G_CALLBACK(playlist_new_button_toggled), NULL);
+  g_signal_connect(playlist_new_public, "toggled",
+                   G_CALLBACK(playlist_new_button_toggled), NULL);
+  g_signal_connect(playlist_new_private, "toggled",
+                   G_CALLBACK(playlist_new_button_toggled), NULL);
+  gtk_table_attach_defaults(GTK_TABLE(table), playlist_new_shared, 0, 1, 1, 2);
+  gtk_table_attach_defaults(GTK_TABLE(table), playlist_new_public, 1, 2, 1, 2);
+  gtk_table_attach_defaults(GTK_TABLE(table), playlist_new_private, 2, 3, 1, 2);
+
+  /* Third row: info bar saying why not */
+  playlist_new_info = gtk_label_new("");
+  gtk_table_attach_defaults(GTK_TABLE(table), playlist_new_info,
+                            0, 3, 2, 3);
+
+  /* Fourth row: ok/cancel buttons */
+  GtkWidget *hbox = create_buttons_box(playlist_new_buttons,
+                                       NPLAYLIST_NEW_BUTTONS,
+                                       gtk_hbox_new(FALSE, 0));
+  gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 3, 3, 4);
+
+  gtk_container_add(GTK_CONTAINER(playlist_new_window),
+                    frame_widget(table, NULL));
+
+  /* Set initial state of OK button */
+  playlist_new_changed(0,0,0);
+
+  /* TODO: return should = OK, escape should = cancel */
+  
+  /* Display the window */
+  gtk_widget_show_all(playlist_new_window);
 }
 
 }
 
-/** @brief Called when the newly created playlist has unlocked */
-static void playlist_new_unlocked(void attribute((unused)) *v, const char *err) {
-  if(err)
-    popup_protocol_error(0, err);
-  /* Pop down the creation window */
-  gtk_widget_destroy(playlist_new_window);
+/** @brief Called when 'ok' is clicked in new-playlist popup */
+static void playlist_new_ok(GtkButton attribute((unused)) *button,
+                            gpointer attribute((unused)) userdata) {
+  gboolean shared, public, private;
+  char *name, *fullname;
+  playlist_new_details(&name, &fullname, &shared, &public, &private);
+
+  /* We need to:
+   * - lock the playlist
+   * - check it doesn't exist
+   * - set sharing (which will create it empty
+   * - unlock it
+   *
+   * TODO we should freeze the window while this is going on to stop a second
+   * click.
+   */
+  disorder_eclient_playlist_lock(client, playlist_new_locked, fullname,
+                                 fullname);
 }
 
 }
 
-/** @brief Called when the new playlist has been created */
-static void playlist_new_created(void attribute((unused)) *v, const char *err) {
+/** @brief Called when the proposed new playlist has been locked */
+static void playlist_new_locked(void *v, const char *err) {
+  char *fullname = v;
   if(err) {
     popup_protocol_error(0, err);
     return;
   }
   if(err) {
     popup_protocol_error(0, err);
     return;
   }
-  disorder_eclient_playlist_unlock(client, playlist_new_unlocked, NULL);
-  // TODO arrange for the new playlist to be selected
+  disorder_eclient_playlist_get(client, playlist_new_retrieved,
+                                fullname, fullname);
 }
 
 /** @brief Called when the proposed new playlist's contents have been retrieved
 }
 
 /** @brief Called when the proposed new playlist's contents have been retrieved
@@ -309,35 +406,22 @@ static void playlist_new_retrieved(void *v, const char *err,
                                       fullname);
 }
 
                                       fullname);
 }
 
-/** @brief Called when the proposed new playlist has been locked */
-static void playlist_new_locked(void *v, const char *err) {
-  char *fullname = v;
+/** @brief Called when the new playlist has been created */
+static void playlist_new_created(void attribute((unused)) *v, const char *err) {
   if(err) {
     popup_protocol_error(0, err);
     return;
   }
   if(err) {
     popup_protocol_error(0, err);
     return;
   }
-  disorder_eclient_playlist_get(client, playlist_new_retrieved,
-                                fullname, fullname);
+  disorder_eclient_playlist_unlock(client, playlist_new_unlocked, NULL);
+  // TODO arrange for the new playlist to be selected
 }
 
 }
 
-/** @brief Called when 'ok' is clicked in new-playlist popup */
-static void playlist_new_ok(GtkButton attribute((unused)) *button,
-                            gpointer attribute((unused)) userdata) {
-  gboolean shared, public, private;
-  char *name, *fullname;
-  playlist_new_details(&name, &fullname, &shared, &public, &private);
-
-  /* We need to:
-   * - lock the playlist
-   * - check it doesn't exist
-   * - set sharing (which will create it empty
-   * - unlock it
-   *
-   * TODO we should freeze the window while this is going on to stop a second
-   * click.
-   */
-  disorder_eclient_playlist_lock(client, playlist_new_locked, fullname,
-                                 fullname);
+/** @brief Called when the newly created playlist has unlocked */
+static void playlist_new_unlocked(void attribute((unused)) *v, const char *err) {
+  if(err)
+    popup_protocol_error(0, err);
+  /* Pop down the creation window */
+  gtk_widget_destroy(playlist_new_window);
 }
 
 /** @brief Called when 'cancel' is clicked in new-playlist popup */
 }
 
 /** @brief Called when 'cancel' is clicked in new-playlist popup */
@@ -346,20 +430,35 @@ static void playlist_new_cancel(GtkButton attribute((unused)) *button,
   gtk_widget_destroy(playlist_new_window);
 }
 
   gtk_widget_destroy(playlist_new_window);
 }
 
-/** @brief Buttons for new-playlist popup */
-static struct button playlist_new_buttons[] = {
-  {
-    .stock = GTK_STOCK_OK,
-    .clicked = playlist_new_ok,
-    .tip = "Create new playlist"
-  },
-  {
-    .stock = GTK_STOCK_CANCEL,
-    .clicked = playlist_new_cancel,
-    .tip = "Do not create new playlist"
-  }
-};
-#define NPLAYLIST_NEW_BUTTONS (sizeof playlist_new_buttons / sizeof *playlist_new_buttons)
+/** @brief Called when some radio button in the new-playlist popup changes */
+static void playlist_new_button_toggled(GtkToggleButton attribute((unused)) *tb,
+                                        gpointer attribute((unused)) userdata) {
+  playlist_new_changed(0,0,0);
+}
+
+/** @brief Called when the text entry field in the new-playlist popup changes */
+static void playlist_new_entry_edited(GtkEditable attribute((unused)) *editable,
+                                      gpointer attribute((unused)) user_data) {
+  playlist_new_changed(0,0,0);
+}
+
+/** @brief Called to update new playlist window state
+ *
+ * This is called whenever one the text entry or radio buttons changed, and
+ * also when the set of known playlists changes.  It determines whether the new
+ * playlist would be creatable and sets the sensitivity of the OK button
+ * and info display accordingly.
+ */
+static void playlist_new_changed(const char attribute((unused)) *event,
+                                 void attribute((unused)) *eventdata,
+                                 void attribute((unused)) *callbackdata) {
+  if(!playlist_new_window)
+    return;
+  const char *reason = playlist_new_valid();
+  gtk_widget_set_sensitive(playlist_new_buttons[0].widget,
+                           !reason);
+  gtk_label_set_text(GTK_LABEL(playlist_new_info), reason);
+}
 
 /** @brief Test whether the new-playlist window settings are valid
  * @return NULL on success or an error string if not
 
 /** @brief Test whether the new-playlist window settings are valid
  * @return NULL on success or an error string if not
@@ -392,101 +491,34 @@ static const char *playlist_new_valid(void) {
   return NULL;
 }
 
   return NULL;
 }
 
-/** @brief Called to update new playlist window state
- *
- * This is called whenever one the text entry or radio buttons changed, and
- * also when the set of known playlists changes.  It determines whether the new
- * playlist would be creatable and sets the sensitivity of the OK button
- * and info display accordingly.
+/** @brief Get entered new-playlist details
+ * @param namep Where to store entered name (or NULL)
+ * @param fullnamep Where to store computed full name (or NULL)
+ * @param sharep Where to store 'shared' flag (or NULL)
+ * @param publicp Where to store 'public' flag (or NULL)
+ * @param privatep Where to store 'private' flag (or NULL)
  */
  */
-static void playlist_new_changed(const char attribute((unused)) *event,
-                                 void attribute((unused)) *eventdata,
-                                 void attribute((unused)) *callbackdata) {
-  if(!playlist_new_window)
-    return;
-  const char *reason = playlist_new_valid();
-  gtk_widget_set_sensitive(playlist_new_buttons[0].widget,
-                           !reason);
-  gtk_label_set_text(GTK_LABEL(playlist_new_info), reason);
-}
-
-/** @brief Called when some radio button in the new-playlist popup changes */
-static void playlist_new_button_toggled(GtkToggleButton attribute((unused)) tb,
-                                        gpointer attribute((unused)) userdata) {
-  playlist_new_changed(0,0,0);
-}
-
-/** @brief Called when the text entry field in the new-playlist popup changes */
-static void playlist_new_entry_edited(GtkEditable attribute((unused)) *editable,
-                                      gpointer attribute((unused)) user_data) {
-  playlist_new_changed(0,0,0);
-}
-
-/** @brief Pop up a new window to enter the playlist name and details */
-static void playlist_new_playlist(void) {
-  assert(playlist_new_window == NULL);
-  playlist_new_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-  g_signal_connect(playlist_new_window, "destroy",
-                  G_CALLBACK(gtk_widget_destroyed), &playlist_new_window);
-  gtk_window_set_title(GTK_WINDOW(playlist_new_window), "Create new playlist");
-  /* Window will be modal, suppressing access to other windows */
-  gtk_window_set_modal(GTK_WINDOW(playlist_new_window), TRUE);
-  gtk_window_set_transient_for(GTK_WINDOW(playlist_new_window),
-                               GTK_WINDOW(playlist_window));
-
-  /* Window contents will use a table (grid) layout */
-  GtkWidget *table = gtk_table_new(3, 3, FALSE/*!homogeneous*/);
-
-  /* First row: playlist name */
-  gtk_table_attach_defaults(GTK_TABLE(table),
-                            gtk_label_new("Playlist name"),
-                            0, 1, 0, 1);
-  playlist_new_entry = gtk_entry_new();
-  g_signal_connect(playlist_new_entry, "changed",
-                   G_CALLBACK(playlist_new_entry_edited), NULL);
-  gtk_table_attach_defaults(GTK_TABLE(table),
-                            playlist_new_entry,
-                            1, 3, 0, 1);
-
-  /* Second row: radio buttons to choose type */
-  playlist_new_shared = gtk_radio_button_new_with_label(NULL, "shared");
-  playlist_new_public
-    = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(playlist_new_shared),
-                                                  "public");
-  playlist_new_private
-    = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(playlist_new_shared),
-                                                  "private");
-  g_signal_connect(playlist_new_shared, "toggled",
-                   G_CALLBACK(playlist_new_button_toggled), NULL);
-  g_signal_connect(playlist_new_public, "toggled",
-                   G_CALLBACK(playlist_new_button_toggled), NULL);
-  g_signal_connect(playlist_new_private, "toggled",
-                   G_CALLBACK(playlist_new_button_toggled), NULL);
-  gtk_table_attach_defaults(GTK_TABLE(table), playlist_new_shared, 0, 1, 1, 2);
-  gtk_table_attach_defaults(GTK_TABLE(table), playlist_new_public, 1, 2, 1, 2);
-  gtk_table_attach_defaults(GTK_TABLE(table), playlist_new_private, 2, 3, 1, 2);
-
-  /* Third row: info bar saying why not */
-  playlist_new_info = gtk_label_new("");
-  gtk_table_attach_defaults(GTK_TABLE(table), playlist_new_info,
-                            0, 3, 2, 3);
-
-  /* Fourth row: ok/cancel buttons */
-  GtkWidget *hbox = create_buttons_box(playlist_new_buttons,
-                                       NPLAYLIST_NEW_BUTTONS,
-                                       gtk_hbox_new(FALSE, 0));
-  gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 3, 3, 4);
-
-  gtk_container_add(GTK_CONTAINER(playlist_new_window),
-                    frame_widget(table, NULL));
-
-  /* Set initial state of OK button */
-  playlist_new_changed(0,0,0);
-
-  /* TODO: return should = OK, escape should = cancel */
-  
-  /* Display the window */
-  gtk_widget_show_all(playlist_new_window);
+static void playlist_new_details(char **namep,
+                                 char **fullnamep,
+                                 gboolean *sharedp,
+                                 gboolean *publicp,
+                                 gboolean *privatep) {
+  gboolean shared, public, private;
+  g_object_get(playlist_new_shared, "active", &shared, (char *)NULL);
+  g_object_get(playlist_new_public, "active", &public, (char *)NULL);
+  g_object_get(playlist_new_private, "active", &private, (char *)NULL);
+  char *gname = gtk_editable_get_chars(GTK_EDITABLE(playlist_new_entry),
+                                       0, -1); /* name owned by calle */
+  char *name = xstrdup(gname);
+  g_free(gname);
+  if(sharedp) *sharedp = shared;
+  if(publicp) *publicp = public;
+  if(privatep) *privatep = private;
+  if(namep) *namep = name;
+  if(fullnamep) {
+    if(*sharedp) *fullnamep = *namep;
+    else byte_xasprintf(fullnamep, "%s.%s", config->username, name);
+  }
 }
 
 /* Playlist picker ---------------------------------------------------------- */
 }
 
 /* Playlist picker ---------------------------------------------------------- */
@@ -657,6 +689,28 @@ static GtkWidget *playlist_picker_create(void) {
 
 /* Playlist editor ---------------------------------------------------------- */
 
 
 /* Playlist editor ---------------------------------------------------------- */
 
+static GtkWidget *playlists_editor_create(void) {
+  assert(ql_playlist.view == NULL);     /* better not be set up already */
+  GtkWidget *w = init_queuelike(&ql_playlist);
+  /* Initially empty */
+  return w;
+}
+
+/** @brief (Re-)populate the playlist tree model */
+static void playlist_editor_fill(const char attribute((unused)) *event,
+                                 void *eventdata,
+                                 void attribute((unused)) *callbackdata) {
+  const char *modified_playlist = eventdata;
+  if(!playlist_window)
+    return;
+  if(!playlist_picker_selected)
+    return;
+  if(!strcmp(playlist_picker_selected, modified_playlist))
+    disorder_eclient_playlist_get(client, playlists_editor_received_tracks,
+                                  playlist_picker_selected,
+                                  (void *)playlist_picker_selected);
+}
+
 /** @brief Called with new tracks for the playlist */
 static void playlists_editor_received_tracks(void *v,
                                              const char *err,
 /** @brief Called with new tracks for the playlist */
 static void playlists_editor_received_tracks(void *v,
                                              const char *err,
@@ -695,28 +749,6 @@ static void playlists_editor_received_tracks(void *v,
   ql_new_queue(&ql_playlist, newq);
 }
 
   ql_new_queue(&ql_playlist, newq);
 }
 
-/** @brief (Re-)populate the playlist tree model */
-static void playlist_editor_fill(const char attribute((unused)) *event,
-                                 void *eventdata,
-                                 void attribute((unused)) *callbackdata) {
-  const char *modified_playlist = eventdata;
-  if(!playlist_window)
-    return;
-  if(!playlist_picker_selected)
-    return;
-  if(!strcmp(playlist_picker_selected, modified_playlist))
-    disorder_eclient_playlist_get(client, playlists_editor_received_tracks,
-                                  playlist_picker_selected,
-                                  (void *)playlist_picker_selected);
-}
-
-static GtkWidget *playlists_editor_create(void) {
-  assert(ql_playlist.view == NULL);     /* better not be set up already */
-  GtkWidget *w = init_queuelike(&ql_playlist);
-  /* Initially empty */
-  return w;
-}
-
 /* Playlist editor right-click menu ---------------------------------------- */
 
 /** @brief Called to determine whether the playlist is playable */
 /* Playlist editor right-click menu ---------------------------------------- */
 
 /** @brief Called to determine whether the playlist is playable */
@@ -770,28 +802,6 @@ static void playlist_remove_activate(GtkMenuItem attribute((unused)) *menuitem,
 
 /* Playlists window --------------------------------------------------------- */
 
 
 /* Playlists window --------------------------------------------------------- */
 
-/** @brief Keypress handler */
-static gboolean playlist_window_keypress(GtkWidget attribute((unused)) *widget,
-                                         GdkEventKey *event,
-                                         gpointer attribute((unused)) user_data) {
-  if(event->state)
-    return FALSE;
-  switch(event->keyval) {
-  case GDK_Escape:
-    gtk_widget_destroy(playlist_window);
-    return TRUE;
-  default:
-    return FALSE;
-  }
-}
-
-/** @brief Called when the playlist window is destroyed */
-static void playlist_window_destroyed(GtkWidget attribute((unused)) *widget,
-                                      GtkWidget **widget_pointer) {
-  destroy_queuelike(&ql_playlist);
-  *widget_pointer = NULL;
-}
-
 /** @brief Pop up the playlists window
  *
  * Called when the playlists menu item is selected
 /** @brief Pop up the playlists window
  *
  * Called when the playlists menu item is selected
@@ -830,6 +840,28 @@ void playlist_window_create(gpointer attribute((unused)) callback_data,
   gtk_widget_show_all(playlist_window);
 }
 
   gtk_widget_show_all(playlist_window);
 }
 
+/** @brief Keypress handler */
+static gboolean playlist_window_keypress(GtkWidget attribute((unused)) *widget,
+                                         GdkEventKey *event,
+                                         gpointer attribute((unused)) user_data) {
+  if(event->state)
+    return FALSE;
+  switch(event->keyval) {
+  case GDK_Escape:
+    gtk_widget_destroy(playlist_window);
+    return TRUE;
+  default:
+    return FALSE;
+  }
+}
+
+/** @brief Called when the playlist window is destroyed */
+static void playlist_window_destroyed(GtkWidget attribute((unused)) *widget,
+                                      GtkWidget **widget_pointer) {
+  destroy_queuelike(&ql_playlist);
+  *widget_pointer = NULL;
+}
+
 /** @brief Initialize playlist support */
 void playlists_init(void) {
   /* We re-get all playlists upon any change... */
 /** @brief Initialize playlist support */
 void playlists_init(void) {
   /* We re-get all playlists upon any change... */