+ disorder_eclient_recent(client, queuelike_completed, &ql_recent);
+}
+
+/* Newly added tracks ------------------------------------------------------ */
+
+/** @brief Pop-up menu for recently played list */
+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 }
+};
+
+/** @brief Create the newly-added list */
+GtkWidget *added_widget(void) {
+ D(("added_widget"));
+ event_register("added-changed", added_changed, 0);
+ return queuelike(&ql_added, 0/*fixup*/, 0/*notify*/, added_menu,
+ addedcolumns, NADDEDCOLUMNS);
+}
+
+/** @brief Called with an updated list of newly-added tracks
+ *
+ * This is called with a raw list of track names but the rest of @ref
+ * disobedience/queue.c requires @ref queue_entry structures with a valid and
+ * unique @c id field. This function fakes it.
+ */
+static void new_completed(void *v,
+ const char *error,
+ int nvec, char **vec) {
+ if(error)
+ popup_protocol_error(0, error);
+ else {
+ struct queuelist *ql = v;
+ /* Convert the vector result to a queue linked list */
+ struct queue_entry *q, *qh, *qlast = 0, **qq = &qh;
+ int n;
+
+ for(n = 0; n < nvec; ++n) {
+ q = xmalloc(sizeof *q);
+ q->prev = qlast;
+ q->track = vec[n];
+ q->id = vec[n];
+ *qq = q;
+ qq = &q->next;
+ qlast = q;
+ }
+ *qq = 0;
+ queuelike_completed(ql, 0, qh);
+ }
+}
+
+/** @brief Update the newly-added list */
+static void added_changed(const char attribute((unused)) *event,
+ void attribute((unused)) *eventdata,
+ void attribute((unused)) *callbackdata) {
+ D(("added_changed"));
+
+ gtk_label_set_text(GTK_LABEL(report_label),
+ "updating newly added track list");
+ disorder_eclient_new_tracks(client, new_completed, 0/*all*/, &ql_added);