chiark / gitweb /
Change version number to 4.0.
[disorder] / clients / test-eclient.c
CommitLineData
460b9539 1/*
2 * This file is part of DisOrder.
3 * Copyright (C) 2006 Richard Kettlewell
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
05b75f8d 21#include "common.h"
460b9539 22
23#include <sys/select.h>
460b9539 24#include <errno.h>
460b9539 25#include <time.h>
26
27#include "queue.h"
28#include "mem.h"
29#include "log.h"
30#include "eclient.h"
31#include "configuration.h"
32#include "syscalls.h"
33#include "wstat.h"
34#include "charset.h"
35
36/* TODO: a more comprehensive test */
37
38static fd_set rfd, wfd;
39static int maxfd;
40static disorder_eclient *clients[1024];
41static char **tracks;
42static disorder_eclient *c;
43static char u_value;
44static int quit;
45
46static const char *modes[] = { "none", "read", "write", "read write" };
47
48static void cb_comms_error(void *u, const char *msg) {
49 assert(u == &u_value);
50 fprintf(stderr, "! comms error: %s\n", msg);
51}
52
53static void cb_protocol_error(void *u,
54 void attribute((unused)) *v,
55 int attribute((unused)) code,
56 const char *msg) {
57 assert(u == &u_value);
58 fprintf(stderr, "! protocol error: %s\n", msg);
59}
60
61static void cb_poll(void *u, disorder_eclient *c_, int fd, unsigned mode) {
62 assert(u == &u_value);
63 assert(fd >= 0);
64 assert(fd < 1024); /* bodge */
65 fprintf(stderr, " poll callback %d %s\n", fd, modes[mode]);
66 if(mode & DISORDER_POLL_READ)
67 FD_SET(fd, &rfd);
68 else
69 FD_CLR(fd, &rfd);
70 if(mode & DISORDER_POLL_WRITE)
71 FD_SET(fd, &wfd);
72 else
73 FD_CLR(fd, &wfd);
74 clients[fd] = mode ? c_ : 0;
75 if(fd > maxfd) maxfd = fd;
76}
77
78static void cb_report(void attribute((unused)) *u,
79 const char attribute((unused)) *msg) {
80}
81
82static const disorder_eclient_callbacks callbacks = {
83 cb_comms_error,
84 cb_protocol_error,
85 cb_poll,
86 cb_report
87};
88
89/* cheap plastic event loop */
90static void loop(void) {
91 int n;
92
93 while(!quit) {
94 fd_set r = rfd, w = wfd;
95 n = select(maxfd + 1, &r, &w, 0, 0);
96 if(n < 0) {
97 if(errno == EINTR) continue;
98 fatal(errno, "select");
99 }
100 for(n = 0; n <= maxfd; ++n)
101 if(clients[n] && (FD_ISSET(n, &r) || FD_ISSET(n, &w)))
102 disorder_eclient_polled(clients[n],
103 ((FD_ISSET(n, &r) ? DISORDER_POLL_READ : 0)
104 |(FD_ISSET(n, &w) ? DISORDER_POLL_WRITE : 0)));
105 }
106 printf(". quit\n");
107}
108
109static void done(void) {
110 printf(". done\n");
111 disorder_eclient_close(c);
112 quit = 1;
113}
114
115static void play_completed(void *v) {
116 assert(v == tracks);
117 printf("* played: %s\n", *tracks);
118 ++tracks;
119 if(*tracks) {
120 if(disorder_eclient_play(c, *tracks, play_completed, tracks))
121 exit(1);
122 } else
123 done();
124}
125
126static void version_completed(void *v, const char *value) {
127 printf("* version: %s\n", value);
128 if(v) {
129 if(*tracks) {
130 if(disorder_eclient_play(c, *tracks, play_completed, tracks))
131 exit(1);
132 } else
133 done();
134 }
135}
136
137/* TODO: de-dupe with disorder.c */
138static void print_queue_entry(const struct queue_entry *q) {
139 if(q->track) xprintf("track %s\n", nullcheck(utf82mb(q->track)));
140 if(q->id) xprintf(" id %s\n", nullcheck(utf82mb(q->id)));
141 if(q->submitter) xprintf(" submitted by %s at %s",
142 nullcheck(utf82mb(q->submitter)), ctime(&q->when));
143 if(q->played) xprintf(" played at %s", ctime(&q->played));
144 if(q->state == playing_started
145 || q->state == playing_paused) xprintf(" %lds so far", q->sofar);
146 else if(q->expected) xprintf(" might start at %s", ctime(&q->expected));
147 if(q->scratched) xprintf(" scratched by %s\n",
148 nullcheck(utf82mb(q->scratched)));
149 else xprintf(" %s\n", playing_states[q->state]);
150 if(q->wstat) xprintf(" %s\n", wstat(q->wstat));
151}
152
153static void recent_completed(void *v, struct queue_entry *q) {
154 assert(v == 0);
155 for(; q; q = q->next)
156 print_queue_entry(q);
157 if(disorder_eclient_version(c, version_completed, (void *)"")) exit(1);
158}
159
160int main(int argc, char **argv) {
161 assert(argc > 0);
320598d4 162 mem_init();
460b9539 163 debugging = 0; /* turn on for even more verbosity */
c00fce3a 164 if(config_read(0)) fatal(0, "config_read failed");
460b9539 165 tracks = &argv[1];
166 c = disorder_eclient_new(&callbacks, &u_value);
167 assert(c != 0);
168 /* stack up several version commands to test pipelining */
169 if(disorder_eclient_version(c, version_completed, 0)) exit(1);
170 if(disorder_eclient_version(c, version_completed, 0)) exit(1);
171 if(disorder_eclient_version(c, version_completed, 0)) exit(1);
172 if(disorder_eclient_version(c, version_completed, 0)) exit(1);
173 if(disorder_eclient_version(c, version_completed, 0)) exit(1);
174 if(disorder_eclient_recent(c, recent_completed, 0)) exit(1);
175 loop();
176 exit(0);
177}
178
179/*
180Local Variables:
181c-basic-offset:2
182comment-column:40
183End:
184*/