redirect(0);
}
+static void act_pause(void) {
+ if(dcgi_client)
+ disorder_pause(dcgi_client);
+ redirect(0);
+}
+
+static void act_resume(void) {
+ if(dcgi_client)
+ disorder_resume(dcgi_client);
+ redirect(0);
+}
+
static void act_remove(void) {
const char *id;
struct queue_entry *q;
redirect(0);
}
+static void act_move(void) {
+ const char *id, *delta;
+ struct queue_entry *q;
+
+ if(dcgi_client) {
+ if(!(id = cgi_get("id")))
+ error(0, "missing 'id' argument");
+ else if(!(delta = cgi_get("delta")))
+ error(0, "missing 'delta' argument");
+ else if(!(q = dcgi_findtrack(id)))
+ error(0, "unknown queue id %s", id);
+ else switch(q->state) {
+ case playing_random: /* unplayed randomly chosen track */
+ case playing_unplayed: /* haven't played this track yet */
+ disorder_move(dcgi_client, id, atol(delta));
+ break;
+ default:
+ error(0, "does not make sense to scratch %s", id);
+ break;
+ }
+ }
+ redirect(0);
+}
+
+static void act_play(void) {
+ const char *track, *dir;
+ char **tracks;
+ int ntracks, n;
+ struct dcgi_entry *e;
+
+ if(dcgi_client) {
+ if((track = cgi_get("file"))) {
+ disorder_play(dcgi_client, track);
+ } else if((dir = cgi_get("dir"))) {
+ if(disorder_files(dcgi_client, dir, 0, &tracks, &ntracks))
+ ntracks = 0;
+ e = xmalloc(ntracks * sizeof (struct dcgi_entry));
+ for(n = 0; n < ntracks; ++n) {
+ e[n].track = tracks[n];
+ e[n].sort = trackname_transform("track", tracks[n], "sort");
+ e[n].display = trackname_transform("track", tracks[n], "display");
+ }
+ qsort(e, ntracks, sizeof (struct dcgi_entry), dcgi_compare_entry);
+ for(n = 0; n < ntracks; ++n)
+ disorder_play(dcgi_client, e[n].track);
+ }
+ }
+ redirect(0);
+}
+
+static int clamp(int n, int min, int max) {
+ if(n < min)
+ return min;
+ if(n > max)
+ return max;
+ return n;
+}
+
+static void act_volume(void) {
+ const char *l, *r, *d;
+ int nd;
+
+ if(dcgi_client) {
+ if((d = cgi_get("delta"))) {
+ dcgi_lookup(DCGI_VOLUME);
+ nd = clamp(atoi(d), -255, 255);
+ disorder_set_volume(dcgi_client,
+ clamp(dcgi_volume_left + nd, 0, 255),
+ clamp(dcgi_volume_right + nd, 0, 255));
+ } else if((l = cgi_get("left")) && (r = cgi_get("right")))
+ disorder_set_volume(dcgi_client, atoi(l), atoi(r));
+ }
+ redirect(0);
+}
+
/** @brief Table of actions */
static const struct action {
/** @brief Action name */
{ "disable", act_disable },
{ "enable", act_enable },
{ "manage", act_playing },
+ { "move", act_move },
+ { "pause", act_pause },
+ { "play", act_play },
{ "playing", act_playing },
{ "randomdisable", act_random_disable },
{ "randomenable", act_random_enable },
{ "remove", act_remove },
+ { "resume", act_resume },
+ { "volume", act_volume },
};
/** @brief Check that an action name is valid
/* actions ********************************************************************/
-static void act_disable(cgi_sink *output,
- dcgi_state *ds) {
- if(ds->g->client)
- disorder_disable(ds->g->client);
- redirect(output->sink);
-}
-
-static void act_enable(cgi_sink *output,
- dcgi_state *ds) {
- if(ds->g->client)
- disorder_enable(ds->g->client);
- redirect(output->sink);
-}
-
-static void act_random_disable(cgi_sink *output,
- dcgi_state *ds) {
- if(ds->g->client)
- disorder_random_disable(ds->g->client);
- redirect(output->sink);
-}
-
-static void act_random_enable(cgi_sink *output,
- dcgi_state *ds) {
- if(ds->g->client)
- disorder_random_enable(ds->g->client);
- redirect(output->sink);
-}
-
-static void act_remove(cgi_sink *output,
- dcgi_state *ds) {
- const char *id;
-
- if(!(id = cgi_get("id"))) fatal(0, "missing id argument");
- if(ds->g->client)
- disorder_remove(ds->g->client, id);
- redirect(output->sink);
-}
-
-static void act_move(cgi_sink *output,
- dcgi_state *ds) {
- const char *id, *delta;
-
- if(!(id = cgi_get("id"))) fatal(0, "missing id argument");
- if(!(delta = cgi_get("delta"))) fatal(0, "missing delta argument");
- if(ds->g->client)
- disorder_move(ds->g->client, id, atoi(delta));
- redirect(output->sink);
-}
-
-static void act_scratch(cgi_sink *output,
- dcgi_state *ds) {
- if(ds->g->client)
- disorder_scratch(ds->g->client, cgi_get("id"));
- redirect(output->sink);
-}
-
-static void act_play(cgi_sink *output,
- dcgi_state *ds) {
- const char *track, *dir;
- char **tracks;
- int ntracks, n;
- struct entry *e;
-
- if((track = cgi_get("file"))) {
- disorder_play(ds->g->client, track);
- } else if((dir = cgi_get("directory"))) {
- if(disorder_files(ds->g->client, dir, 0, &tracks, &ntracks)) ntracks = 0;
- if(ntracks) {
- e = xmalloc(ntracks * sizeof (struct entry));
- for(n = 0; n < ntracks; ++n) {
- e[n].path = tracks[n];
- e[n].sort = trackname_transform("track", tracks[n], "sort");
- e[n].display = trackname_transform("track", tracks[n], "display");
- }
- qsort(e, ntracks, sizeof (struct entry), compare_entry);
- for(n = 0; n < ntracks; ++n)
- disorder_play(ds->g->client, e[n].path);
- }
- }
- /* XXX error handling */
- redirect(output->sink);
-}
-
-static int clamp(int n, int min, int max) {
- if(n < min)
- return min;
- if(n > max)
- return max;
- return n;
-}
-
-static const char *volume_url(void) {
- char *url;
-
- byte_xasprintf(&url, "%s?action=volume", config->url);
- return url;
-}
-
-static void act_volume(cgi_sink *output, dcgi_state *ds) {
- const char *l, *r, *d, *back;
- int nd, changed = 0;;
-
- if((d = cgi_get("delta"))) {
- lookups(ds, DC_VOLUME);
- nd = clamp(atoi(d), -255, 255);
- disorder_set_volume(ds->g->client,
- clamp(ds->g->volume_left + nd, 0, 255),
- clamp(ds->g->volume_right + nd, 0, 255));
- changed = 1;
- } else if((l = cgi_get("left")) && (r = cgi_get("right"))) {
- disorder_set_volume(ds->g->client, atoi(l), atoi(r));
- changed = 1;
- }
- if(changed) {
- /* redirect back to ourselves (but without the volume-changing bits in the
- * URL) */
- cgi_header(output->sink, "Location",
- (back = cgi_get("back")) ? back : volume_url());
- header_cookie(output->sink);
- cgi_body(output->sink);
- } else {
- cgi_header(output->sink, "Content-Type", "text/html");
- header_cookie(output->sink);
- cgi_body(output->sink);
- expand(output, "volume", ds);
- }
-}
-
static void act_prefs_errors(const char *msg,
void attribute((unused)) *u) {
fatal(0, "error splitting parts list: %s", msg);
expand(output, "prefs", ds);
}
-static void act_pause(cgi_sink *output,
- dcgi_state *ds) {
- if(ds->g->client)
- disorder_pause(ds->g->client);
- redirect(output->sink);
-}
-
-static void act_resume(cgi_sink *output,
- dcgi_state *ds) {
- if(ds->g->client)
- disorder_resume(ds->g->client);
- redirect(output->sink);
-}
-
static void act_login(cgi_sink *output,
dcgi_state *ds) {
const char *username, *password, *back;
extern char *dcgi_cookie;
extern char *dcgi_error_string;
+/** @brief Entry in a list of tracks or directories */
+struct dcgi_entry {
+ /** @brief Track name */
+ const char *track;
+ /** @brief Sort key */
+ const char *sort;
+ /** @brief Display key */
+ const char *display;
+};
+
+/** @brief Compare two @ref entry objects */
+int dcgi_compare_entry(const void *a, const void *b);
+
void dcgi_expand(const char *name);
void dcgi_action(const char *action);
void dcgi_error(const char *key);
#define DCGI_PLAYING 0x0002
#define DCGI_RECENT 0x0004
#define DCGI_VOLUME 0x0008
-#if 0
-#define DCGI_DIRS 0x0010
-#define DCGI_FILES 0x0020
-#endif
#define DCGI_NEW 0x0040
#define DCGI_RIGHTS 0x0080
#define DCGI_ENABLED 0x0100
void dcgi_lookup(unsigned want) {
unsigned need = want ^ (flags & want);
struct queue_entry *r, *rnext;
-#if 0
- const char *dir, *re;
-#endif
char *rs;
if(!dcgi_client || !need)
if(need & DCGI_VOLUME)
disorder_get_volume(dcgi_client,
&dcgi_volume_left, &dcgi_volume_right);
-#if 0
- /* DCGI_FILES and DCGI_DIRS are looking obsolete now */
- if(need & (DCGI_FILES|DCGI_DIRS)) {
- if(!(dir = cgi_get("directory")))
- dir = "";
- re = cgi_get("regexp");
- if(need & DCGI_DIRS)
- if(disorder_directories(dcgi_client, dir, re,
- &dirs, &ndirs))
- ndirs = 0;
- if(need & DCGI_FILES)
- if(disorder_files(dcgi_client, dir, re,
- &files, &nfiles))
- nfiles = 0;
- }
-#endif
if(need & DCGI_RIGHTS) {
dcgi_rights = RIGHT_READ; /* fail-safe */
if(!disorder_userinfo(dcgi_client, disorder_user(dcgi_client),
return sink_writes(output, cgi_sgmlquote(url)) < 0 ? -1 : 0;
}
-/** @brief Entry in a list of tracks or directories */
-struct entry {
- /** @brief Track name */
- const char *track;
- /** @brief Sort key */
- const char *sort;
- /** @brief Display key */
- const char *display;
-};
-
/** @brief Compare two @ref entry objects */
-static int compare_entry(const void *a, const void *b) {
- const struct entry *ea = a, *eb = b;
+int dcgi_compare_entry(const void *a, const void *b) {
+ const struct dcgi_entry *ea = a, *eb = b;
return compare_tracks(ea->sort, eb->sort,
ea->display, eb->display,
char **tracks, *dir, *re;
int n, ntracks, rc;
const struct mx_node *m;
- struct entry *e;
+ struct dcgi_entry *e;
if((rc = mx_expandstr(args[0], &dir, u, "argument #0 (DIR)")))
return rc;
e[n].sort = trackname_transform(type, tracks[n], "sort");
e[n].display = trackname_transform(type, tracks[n], "display");
}
- qsort(e, ntracks, sizeof (struct entry), compare_entry);
+ qsort(e, ntracks, sizeof (struct dcgi_entry), dcgi_compare_entry);
/* Expand the subsiduary templates. We chuck in @sort and @display because
* it is particularly easy to do so. */
for(n = 0; n < ntracks; ++n)