From f08c0859513712f805da09ae1e1bcefb436b4096 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Sat, 13 Oct 2007 11:39:21 +0100 Subject: [PATCH] split up queue.c to remove -ldl dependency from clients Organization: Straylight/Edgeware From: Richard Kettlewell --- clients/Makefile.am | 4 +- configure.ac | 2 - lib/queue.c | 292 ------------------------------------- lib/queue.h | 51 ------- server/Makefile.am | 1 + server/play.c | 1 + server/server-queue.c | 330 ++++++++++++++++++++++++++++++++++++++++++ server/server-queue.h | 82 +++++++++++ server/server.c | 1 + server/state.c | 1 + 10 files changed, 418 insertions(+), 347 deletions(-) create mode 100644 server/server-queue.c create mode 100644 server/server-queue.h diff --git a/clients/Makefile.am b/clients/Makefile.am index 858335e..880f86a 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -26,7 +26,7 @@ AM_CPPFLAGS=-I${top_srcdir}/lib -I../lib disorder_SOURCES=disorder.c authorize.c authorize.h \ ../lib/memgc.c disorder_LDADD=$(LIBOBJS) ../lib/libdisorder.a \ - $(LIBDL) $(LIBGC) $(LIBGCRYPT) $(LIBPCRE) + $(LIBGC) $(LIBGCRYPT) $(LIBPCRE) disorder_DEPENDENCIES=$(LIBOBJS) ../lib/libdisorder.a disorderfm_SOURCES=disorderfm.c \ @@ -45,7 +45,7 @@ filename_bytes_SOURCES=filename-bytes.c test_eclient_SOURCES=test-eclient.c \ ../lib/memgc.c test_eclient_LDADD=../lib/libdisorder.a \ - $(LIBDL) $(LIBGC) $(LIBGCRYPT) $(LIBPCRE) + $(LIBGC) $(LIBGCRYPT) $(LIBPCRE) test_eclient_DEPENDENCIES=../lib/libdisorder.a install-exec-hook: diff --git a/configure.ac b/configure.ac index bf0a7b7..6b6236b 100644 --- a/configure.ac +++ b/configure.ac @@ -67,8 +67,6 @@ case "$host" in # work around broken toolchain AC_CHECK_LIB([gpg-error], [gpg_strerror]) AC_CHECK_LIB([pthread], [pthread_create]) - # lib/queue.c really wants to be split into server and non-server bits - AC_CHECK_LIB([dl], [dlopen]) want_server=no ;; *linux* | *Linux* ) diff --git a/lib/queue.c b/lib/queue.c index 940fde3..466fe7b 100644 --- a/lib/queue.c +++ b/lib/queue.c @@ -24,27 +24,15 @@ #include #include #include -#include -#include #include -#include -#include -#include #include "mem.h" #include "queue.h" #include "log.h" -#include "configuration.h" #include "split.h" #include "syscalls.h" -#include "charset.h" #include "table.h" -#include "inputline.h" #include "printf.h" -#include "plugin.h" -#include "basen.h" -#include "eventlog.h" -#include "disorder.h" const char *playing_states[] = { "failed", @@ -59,29 +47,6 @@ const char *playing_states[] = { "unplayed" }; -/* the head of the queue is played next, so normally we add to the tail */ -struct queue_entry qhead = { &qhead, &qhead, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -/* the head of the recent list is the oldest thing, the tail the most recently - * played */ -struct queue_entry phead = { &phead, &phead, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -static long pcount; - -/* add new entry @n@ to a doubly linked list just after @b@ */ -static void l_add(struct queue_entry *b, struct queue_entry *n) { - n->prev = b; - n->next = b->next; - n->next->prev = n; - n->prev->next = n; -} - -/* remove an entry from a doubly-linked list */ -static void l_remove(struct queue_entry *node) { - node->next->prev = node->prev; - node->prev->next = node->next; -} - #define VALUE(q, offset, type) *(type *)((char *)q + offset) static int unmarshall_long(char *data, struct queue_entry *q, @@ -224,30 +189,6 @@ int queue_unmarshall_vec(struct queue_entry *q, int nvec, char **vec, return 0; } -void queue_fix_sofar(struct queue_entry *q) { - long sofar; - - /* Fake up SOFAR field for currently-playing tracks that don't have it filled - * in by the speaker process. XXX this horrible bodge should go away when we - * have a more general implementation of pausing as that field will always - * have to be right for the playing track. */ - if((q->state == playing_started - || q->state == playing_paused) - && q->type & DISORDER_PLAYER_PAUSES - && (q->type & DISORDER_PLAYER_TYPEMASK) != DISORDER_PLAYER_RAW) { - if(q->lastpaused) { - if(q->uptopause == -1) /* Don't know how far thru. */ - sofar = -1; - else if(q->lastresumed) /* Has been paused and resumed. */ - sofar = q->uptopause + time(0) - q->lastresumed; - else /* Currently paused. */ - sofar = q->uptopause; - } else /* Never been paused. */ - sofar = time(0) - q->played; - q->sofar = sofar; - } -} - char *queue_marshall(const struct queue_entry *q) { unsigned n; const char *vec[sizeof fields / sizeof *fields], *v; @@ -271,239 +212,6 @@ char *queue_marshall(const struct queue_entry *q) { return r; } -static void queue_read_error(const char *msg, - void *u) { - fatal(0, "error parsing queue %s: %s", (const char *)u, msg); -} - -static void queue_do_read(struct queue_entry *head, const char *path) { - char *buffer; - FILE *fp; - struct queue_entry *q; - - if(!(fp = fopen(path, "r"))) { - if(errno == ENOENT) - return; /* no queue */ - fatal(errno, "error opening %s", path); - } - head->next = head->prev = head; - while(!inputline(path, fp, &buffer, '\n')) { - q = xmalloc(sizeof *q); - queue_unmarshall(q, buffer, queue_read_error, (void *)path); - if(head == &qhead - && (!q->track - || !q->when)) - fatal(0, "incomplete queue entry in %s", path); - l_add(head->prev, q); - } - if(ferror(fp)) fatal(errno, "error reading %s", path); - fclose(fp); -} - -void queue_read(void) { - queue_do_read(&qhead, config_get_file("queue")); -} - -void recent_read(void) { - struct queue_entry *q; - - queue_do_read(&phead, config_get_file("recent")); - /* reset pcount after loading */ - pcount = 0; - q = phead.next; - while(q != &phead) { - ++pcount; - q = q->next; - } -} - -static void queue_do_write(const struct queue_entry *head, const char *path) { - char *tmp; - FILE *fp; - struct queue_entry *q; - - byte_xasprintf(&tmp, "%s.new", path); - if(!(fp = fopen(tmp, "w"))) fatal(errno, "error opening %s", tmp); - for(q = head->next; q != head; q = q->next) - if(fprintf(fp, "%s\n", queue_marshall(q)) < 0) - fatal(errno, "error writing %s", tmp); - if(fclose(fp) < 0) fatal(errno, "error closing %s", tmp); - if(rename(tmp, path) < 0) fatal(errno, "error replacing %s", path); -} - -void queue_write(void) { - queue_do_write(&qhead, config_get_file("queue")); -} - -void recent_write(void) { - queue_do_write(&phead, config_get_file("recent")); -} - -void queue_id(struct queue_entry *q) { - static unsigned long serial; - unsigned long a[3]; - char buffer[128]; - - a[0] = serial++ & 0xFFFFFFFFUL; - a[1] = time(0) & 0xFFFFFFFFUL; - a[2] = getpid() & 0xFFFFFFFFUL; - basen(a, 3, buffer, sizeof buffer, 62); - q->id = xstrdup(buffer); -} - -struct queue_entry *queue_add(const char *track, const char *submitter, - int where) { - struct queue_entry *q, *beforeme; - - q = xmalloc(sizeof *q); - q->track = xstrdup(track); - q->submitter = submitter ? xstrdup(submitter) : 0; - q->state = playing_unplayed; - queue_id(q); - time(&q->when); - switch(where) { - case WHERE_START: - l_add(&qhead, q); - break; - case WHERE_END: - l_add(qhead.prev, q); - break; - case WHERE_BEFORE_RANDOM: - /* We want to find the point in the queue before the block of random tracks - * at the end. */ - beforeme = &qhead; - while(beforeme->prev != &qhead - && beforeme->prev->state == playing_random) - beforeme = beforeme->prev; - l_add(beforeme->prev, q); - break; - } - /* submitter will be a null pointer for a scratch */ - if(submitter) - notify_queue(track, submitter); - eventlog_raw("queue", queue_marshall(q), (const char *)0); - return q; -} - -int queue_move(struct queue_entry *q, int delta, const char *who) { - int moved = 0; - char buffer[20]; - - /* not the most efficient approach but hopefuly relatively comprehensible: - * the idea is that for each step we determine which nodes are affected, and - * fill in all the links starting at the 'prev' end and moving towards the - * 'next' end. */ - - while(delta > 0 && q->prev != &qhead) { - struct queue_entry *n, *p, *pp; - - n = q->next; - p = q->prev; - pp = p->prev; - pp->next = q; - q->prev = pp; - q->next = p; - p->prev = q; - p->next = n; - n->prev = p; - --delta; - ++moved; - } - - while(delta < 0 && q->next != &qhead) { - struct queue_entry *n, *p, *nn; - - p = q->prev; - n = q->next; - nn = n->next; - p->next = n; - n->prev = p; - n->next = q; - q->prev = n; - q->next = nn; - nn->prev = q; - ++delta; - --moved; - } - - if(moved) { - info("user %s moved %s", who, q->id); - notify_queue_move(q->track, who); - sprintf(buffer, "%d", moved); - eventlog("moved", who, (char *)0); - } - - return delta; -} - -static int find_in_list(struct queue_entry *needle, - int nqs, struct queue_entry **qs) { - int n; - - for(n = 0; n < nqs; ++n) - if(qs[n] == needle) - return 1; - return 0; -} - -void queue_moveafter(struct queue_entry *target, - int nqs, struct queue_entry **qs, - const char *who) { - struct queue_entry *q; - int n; - - /* Normalize */ - if(!target) - target = &qhead; - else - while(find_in_list(target, nqs, qs)) - target = target->prev; - /* Do the move */ - for(n = 0; n < nqs; ++n) { - q = qs[n]; - l_remove(q); - l_add(target, q); - target = q; - /* Log the individual tracks */ - info("user %s moved %s", who, q->id); - notify_queue_move(q->track, who); - } - /* Report that the queue changed to the event log */ - eventlog("moved", who, (char *)0); -} - -void queue_remove(struct queue_entry *which, const char *who) { - if(who) { - info("user %s removed %s", who, which->id); - notify_queue_move(which->track, who); - } - eventlog("removed", which->id, who, (const char *)0); - l_remove(which); -} - -struct queue_entry *queue_find(const char *key) { - struct queue_entry *q; - - for(q = qhead.next; - q != &qhead && strcmp(q->track, key) && strcmp(q->id, key); - q = q->next) - ; - return q != &qhead ? q : 0; -} - -void queue_played(struct queue_entry *q) { - while(pcount && pcount >= config->history) { - eventlog("recent_removed", phead.next->id, (char *)0); - l_remove(phead.next); - pcount--; - } - if(config->history) { - eventlog_raw("recent_added", queue_marshall(q), (char *)0); - l_add(phead.prev, q); - ++pcount; - } -} - /* Local Variables: c-basic-offset:2 diff --git a/lib/queue.h b/lib/queue.h index fa9aa81..3ae4c26 100644 --- a/lib/queue.h +++ b/lib/queue.h @@ -61,41 +61,6 @@ struct queue_entry { struct queuelike *ql; /* owning queue */ }; -extern struct queue_entry qhead; -/* queue of things yet to be played. the head will be played - * soonest. */ - -extern struct queue_entry phead; -/* things that have been played in the past. the head is the oldest. */ - -void queue_read(void); -/* read the queue in. Calls @fatal@ on error. */ - -void queue_write(void); -/* write the queue out. Calls @fatal@ on error. */ - -void recent_read(void); -/* read the recently played list in. Calls @fatal@ on error. */ - -void recent_write(void); -/* write the recently played list out. Calls @fatal@ on error. */ - -struct queue_entry *queue_add(const char *track, const char *submitter, - int where); -#define WHERE_START 0 /* Add to head of queue */ -#define WHERE_END 1 /* Add to end of queue */ -#define WHERE_BEFORE_RANDOM 2 /* End, or before random track */ -/* add an entry to the queue. Return a pointer to the new entry. */ - -void queue_remove(struct queue_entry *q, const char *who); -/* remove an from the queue */ - -struct queue_entry *queue_find(const char *key); -/* find a track in the queue by name or ID */ - -void queue_played(struct queue_entry *q); -/* add @q@ to the played list */ - int queue_unmarshall(struct queue_entry *q, const char *s, void (*error_handler)(const char *, void *), void *u); @@ -109,22 +74,6 @@ int queue_unmarshall_vec(struct queue_entry *q, int nvec, char **vec, char *queue_marshall(const struct queue_entry *q); /* marshall @q@ into a UTF-8 string */ -void queue_id(struct queue_entry *q); -/* give @q@ an ID */ - -int queue_move(struct queue_entry *q, int delta, const char *who); -/* move element @q@ in the queue towards the front (@delta@ > 0) or towards the - * back (@delta@ < 0). The return value is the leftover delta once we've hit - * the end in whichever direction we were going. */ - -void queue_moveafter(struct queue_entry *target, - int nqs, struct queue_entry **qs, const char *who); -/* Move all the elements QS to just after TARGET, or to the head if - * TARGET=0. */ - -void queue_fix_sofar(struct queue_entry *q); -/* Fix up the sofar field for standalone players */ - #endif /* QUEUE_H */ /* diff --git a/server/Makefile.am b/server/Makefile.am index 8fc3dfe..75acf59 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -30,6 +30,7 @@ disorderd_SOURCES=disorderd.c \ daemonize.c daemonize.h \ play.c play.h \ server.c server.h \ + server-queue.c server-queue.h \ state.c state.h \ trackdb.c trackdb.h trackdb-int.h exports.c \ ../lib/memgc.c diff --git a/server/play.c b/server/play.c index 1ca6434..1320e45 100644 --- a/server/play.c +++ b/server/play.c @@ -43,6 +43,7 @@ #include "mem.h" #include "configuration.h" #include "queue.h" +#include "server-queue.h" #include "trackdb.h" #include "play.h" #include "plugin.h" diff --git a/server/server-queue.c b/server/server-queue.c new file mode 100644 index 0000000..2b0e89e --- /dev/null +++ b/server/server-queue.c @@ -0,0 +1,330 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2004, 2005, 2006, 2007 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include "types.h" + +#include +#include +#include +#include +#include + +#include "mem.h" +#include "log.h" +#include "split.h" +#include "printf.h" +#include "queue.h" +#include "server-queue.h" +#include "eventlog.h" +#include "plugin.h" +#include "basen.h" +#include "configuration.h" +#include "inputline.h" +#include "disorder.h" + +/* the head of the queue is played next, so normally we add to the tail */ +struct queue_entry qhead = { &qhead, &qhead, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* the head of the recent list is the oldest thing, the tail the most recently + * played */ +struct queue_entry phead = { &phead, &phead, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +static long pcount; + +/* add new entry @n@ to a doubly linked list just after @b@ */ +static void l_add(struct queue_entry *b, struct queue_entry *n) { + n->prev = b; + n->next = b->next; + n->next->prev = n; + n->prev->next = n; +} + +/* remove an entry from a doubly-linked list */ +static void l_remove(struct queue_entry *node) { + node->next->prev = node->prev; + node->prev->next = node->next; +} + +void queue_fix_sofar(struct queue_entry *q) { + long sofar; + + /* Fake up SOFAR field for currently-playing tracks that don't have it filled + * in by the speaker process. XXX this horrible bodge should go away when we + * have a more general implementation of pausing as that field will always + * have to be right for the playing track. */ + if((q->state == playing_started + || q->state == playing_paused) + && q->type & DISORDER_PLAYER_PAUSES + && (q->type & DISORDER_PLAYER_TYPEMASK) != DISORDER_PLAYER_RAW) { + if(q->lastpaused) { + if(q->uptopause == -1) /* Don't know how far thru. */ + sofar = -1; + else if(q->lastresumed) /* Has been paused and resumed. */ + sofar = q->uptopause + time(0) - q->lastresumed; + else /* Currently paused. */ + sofar = q->uptopause; + } else /* Never been paused. */ + sofar = time(0) - q->played; + q->sofar = sofar; + } +} + +static void queue_read_error(const char *msg, + void *u) { + fatal(0, "error parsing queue %s: %s", (const char *)u, msg); +} + +static void queue_do_read(struct queue_entry *head, const char *path) { + char *buffer; + FILE *fp; + struct queue_entry *q; + + if(!(fp = fopen(path, "r"))) { + if(errno == ENOENT) + return; /* no queue */ + fatal(errno, "error opening %s", path); + } + head->next = head->prev = head; + while(!inputline(path, fp, &buffer, '\n')) { + q = xmalloc(sizeof *q); + queue_unmarshall(q, buffer, queue_read_error, (void *)path); + if(head == &qhead + && (!q->track + || !q->when)) + fatal(0, "incomplete queue entry in %s", path); + l_add(head->prev, q); + } + if(ferror(fp)) fatal(errno, "error reading %s", path); + fclose(fp); +} + +void queue_read(void) { + queue_do_read(&qhead, config_get_file("queue")); +} + +void recent_read(void) { + struct queue_entry *q; + + queue_do_read(&phead, config_get_file("recent")); + /* reset pcount after loading */ + pcount = 0; + q = phead.next; + while(q != &phead) { + ++pcount; + q = q->next; + } +} + +static void queue_do_write(const struct queue_entry *head, const char *path) { + char *tmp; + FILE *fp; + struct queue_entry *q; + + byte_xasprintf(&tmp, "%s.new", path); + if(!(fp = fopen(tmp, "w"))) fatal(errno, "error opening %s", tmp); + for(q = head->next; q != head; q = q->next) + if(fprintf(fp, "%s\n", queue_marshall(q)) < 0) + fatal(errno, "error writing %s", tmp); + if(fclose(fp) < 0) fatal(errno, "error closing %s", tmp); + if(rename(tmp, path) < 0) fatal(errno, "error replacing %s", path); +} + +void queue_write(void) { + queue_do_write(&qhead, config_get_file("queue")); +} + +void recent_write(void) { + queue_do_write(&phead, config_get_file("recent")); +} + +static void queue_id(struct queue_entry *q) { + static unsigned long serial; + unsigned long a[3]; + char buffer[128]; + + a[0] = serial++ & 0xFFFFFFFFUL; + a[1] = time(0) & 0xFFFFFFFFUL; + a[2] = getpid() & 0xFFFFFFFFUL; + basen(a, 3, buffer, sizeof buffer, 62); + q->id = xstrdup(buffer); +} + +struct queue_entry *queue_add(const char *track, const char *submitter, + int where) { + struct queue_entry *q, *beforeme; + + q = xmalloc(sizeof *q); + q->track = xstrdup(track); + q->submitter = submitter ? xstrdup(submitter) : 0; + q->state = playing_unplayed; + queue_id(q); + time(&q->when); + switch(where) { + case WHERE_START: + l_add(&qhead, q); + break; + case WHERE_END: + l_add(qhead.prev, q); + break; + case WHERE_BEFORE_RANDOM: + /* We want to find the point in the queue before the block of random tracks + * at the end. */ + beforeme = &qhead; + while(beforeme->prev != &qhead + && beforeme->prev->state == playing_random) + beforeme = beforeme->prev; + l_add(beforeme->prev, q); + break; + } + /* submitter will be a null pointer for a scratch */ + if(submitter) + notify_queue(track, submitter); + eventlog_raw("queue", queue_marshall(q), (const char *)0); + return q; +} + +int queue_move(struct queue_entry *q, int delta, const char *who) { + int moved = 0; + char buffer[20]; + + /* not the most efficient approach but hopefuly relatively comprehensible: + * the idea is that for each step we determine which nodes are affected, and + * fill in all the links starting at the 'prev' end and moving towards the + * 'next' end. */ + + while(delta > 0 && q->prev != &qhead) { + struct queue_entry *n, *p, *pp; + + n = q->next; + p = q->prev; + pp = p->prev; + pp->next = q; + q->prev = pp; + q->next = p; + p->prev = q; + p->next = n; + n->prev = p; + --delta; + ++moved; + } + + while(delta < 0 && q->next != &qhead) { + struct queue_entry *n, *p, *nn; + + p = q->prev; + n = q->next; + nn = n->next; + p->next = n; + n->prev = p; + n->next = q; + q->prev = n; + q->next = nn; + nn->prev = q; + ++delta; + --moved; + } + + if(moved) { + info("user %s moved %s", who, q->id); + notify_queue_move(q->track, who); + sprintf(buffer, "%d", moved); + eventlog("moved", who, (char *)0); + } + + return delta; +} + +static int find_in_list(struct queue_entry *needle, + int nqs, struct queue_entry **qs) { + int n; + + for(n = 0; n < nqs; ++n) + if(qs[n] == needle) + return 1; + return 0; +} + +void queue_moveafter(struct queue_entry *target, + int nqs, struct queue_entry **qs, + const char *who) { + struct queue_entry *q; + int n; + + /* Normalize */ + if(!target) + target = &qhead; + else + while(find_in_list(target, nqs, qs)) + target = target->prev; + /* Do the move */ + for(n = 0; n < nqs; ++n) { + q = qs[n]; + l_remove(q); + l_add(target, q); + target = q; + /* Log the individual tracks */ + info("user %s moved %s", who, q->id); + notify_queue_move(q->track, who); + } + /* Report that the queue changed to the event log */ + eventlog("moved", who, (char *)0); +} + +void queue_remove(struct queue_entry *which, const char *who) { + if(who) { + info("user %s removed %s", who, which->id); + notify_queue_move(which->track, who); + } + eventlog("removed", which->id, who, (const char *)0); + l_remove(which); +} + +struct queue_entry *queue_find(const char *key) { + struct queue_entry *q; + + for(q = qhead.next; + q != &qhead && strcmp(q->track, key) && strcmp(q->id, key); + q = q->next) + ; + return q != &qhead ? q : 0; +} + +void queue_played(struct queue_entry *q) { + while(pcount && pcount >= config->history) { + eventlog("recent_removed", phead.next->id, (char *)0); + l_remove(phead.next); + pcount--; + } + if(config->history) { + eventlog_raw("recent_added", queue_marshall(q), (char *)0); + l_add(phead.prev, q); + ++pcount; + } +} + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/ diff --git a/server/server-queue.h b/server/server-queue.h new file mode 100644 index 0000000..624f203 --- /dev/null +++ b/server/server-queue.h @@ -0,0 +1,82 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2004, 2005, 2006, 2007 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifndef SERVER_QUEUE_H +#define SERVER_QUEUE_H + +extern struct queue_entry qhead; +/* queue of things yet to be played. the head will be played + * soonest. */ + +extern struct queue_entry phead; +/* things that have been played in the past. the head is the oldest. */ + +void queue_read(void); +/* read the queue in. Calls @fatal@ on error. */ + +void queue_write(void); +/* write the queue out. Calls @fatal@ on error. */ + +void recent_read(void); +/* read the recently played list in. Calls @fatal@ on error. */ + +void recent_write(void); +/* write the recently played list out. Calls @fatal@ on error. */ + +struct queue_entry *queue_add(const char *track, const char *submitter, + int where); +#define WHERE_START 0 /* Add to head of queue */ +#define WHERE_END 1 /* Add to end of queue */ +#define WHERE_BEFORE_RANDOM 2 /* End, or before random track */ +/* add an entry to the queue. Return a pointer to the new entry. */ + +void queue_remove(struct queue_entry *q, const char *who); +/* remove an from the queue */ + +struct queue_entry *queue_find(const char *key); +/* find a track in the queue by name or ID */ + +void queue_played(struct queue_entry *q); +/* add @q@ to the played list */ + +int queue_move(struct queue_entry *q, int delta, const char *who); +/* move element @q@ in the queue towards the front (@delta@ > 0) or towards the + * back (@delta@ < 0). The return value is the leftover delta once we've hit + * the end in whichever direction we were going. */ + +void queue_moveafter(struct queue_entry *target, + int nqs, struct queue_entry **qs, const char *who); +/* Move all the elements QS to just after TARGET, or to the head if + * TARGET=0. */ + +void queue_fix_sofar(struct queue_entry *q); +/* Fix up the sofar field for standalone players */ + +#endif /* SERVER_QUEUE_H */ + + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/ diff --git a/server/server.c b/server/server.c index 4ba43a6..2875ffb 100644 --- a/server/server.c +++ b/server/server.c @@ -42,6 +42,7 @@ #include "server.h" #include "syscalls.h" #include "queue.h" +#include "server-queue.h" #include "play.h" #include "log.h" #include "mem.h" diff --git a/server/state.c b/server/state.c index 45954f0..4ff2654 100644 --- a/server/state.c +++ b/server/state.c @@ -41,6 +41,7 @@ #include "configuration.h" #include "log.h" #include "queue.h" +#include "server-queue.h" #include "server.h" #include "printf.h" #include "addr.h" -- [mdw]