chiark / gitweb /
Formatting.
[disorder] / scripts / protocol
1 #! /usr/bin/perl -w
2 #
3 # This file is part of DisOrder.
4 # Copyright (C) 2010 Richard Kettlewell
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19 use strict;
20
21 # Variables and utilities -----------------------------------------------------
22
23 our @h = ();
24 our @c = ();
25
26 sub Write {
27     my $path = shift;
28     my $lines = shift;
29
30     (open(F, ">$path")
31      and print F @$lines
32      and close F)
33         or die "$0: $path: $!\n";
34 }
35
36 # Command classes -------------------------------------------------------------
37
38 # simple(CMD, SUMMARY, DETAIL, [[NAME,DESCR], [NAME,DESCR], ...],)
39 #
40 # Response is simply success/failure
41 sub simple {
42     my $cmd = shift;
43     my $summary = shift;
44     my $detail = shift;
45     my $args = shift;
46
47     my $cmdc = $cmd;
48     $cmdc =~ s/-/_/g;
49     # Synchronous C API
50     push(@h, "/** \@brief $summary\n",
51          " *\n",
52          " * $detail\n",
53          " *\n",
54          map(" * \@param $_->[0] $_->[1]\n", @$args),
55          " * \@return 0 on success, non-0 on error\n",
56          " */\n",
57          "int disorder_$cmdc(disorder_client *c",
58          map(", const char *$_->[0]", @$args), ");\n",
59          "\n");
60     push(@c, "int disorder_$cmdc(disorder_client *c",
61          map(", const char *$_->[0]", @$args), ") {\n",
62          "  return disorder_simple(c, 0, \"$cmd\"",
63          map(", $_->[0]", @$args),
64          ", (char *)0);\n",
65          "}\n\n");
66
67     # Asynchronous C API
68     # TODO
69
70     # Python API
71     # TODO
72
73     # Java API
74     # TODO
75 }
76
77 # boolean(CMD, SUMMARY, DETAIL, [[NAME,DESCR], [NAME,DESCR], ...], [RETURN, DESCR])
78 #
79 # Response is yes/no or failure
80 sub boolean {
81     my $cmd = shift;
82     my $summary = shift;
83     my $detail = shift;
84     my $args = shift;
85     my $return = shift;
86
87     my $cmdc = $cmd;
88     $cmdc =~ s/-/_/g;
89     # Synchronous C API
90     push(@h, "/** \@brief $summary\n",
91          " *\n",
92          " * $detail\n",
93          " *\n",
94          map(" * \@param $_->[0] $_->[1]\n", @$args),
95          " * \@param $return->[0] $return->[1]\n",
96          " * \@return 0 on success, non-0 on error\n",
97          " */\n",
98          "int disorder_$cmdc(disorder_client *c",
99          map(", const char *$_->[0]", @$args),
100          ", int *$return->[0]);\n",
101          "\n");
102     push(@c, "int disorder_$cmdc(disorder_client *c",
103          map(", const char *$_->[0]", @$args),
104          ", int *$return->[0]) {\n",
105          "  char *v;\n",
106          "  int rc = disorder_simple(c, &v, \"$cmd\"",
107          map(", $_->[0]", @$args),
108          ", (char *)0);\n",
109          "  if(rc) return rc;\n",
110          "  if(!strcmp(v, \"yes\")) *$return->[0] = 1;\n",
111          "  if(!strcmp(v, \"no\")) *$return->[0] = 0;\n",
112          "  else {\n",
113          "    disorder_error(0, \"malformed response to '$cmd' command\");\n",
114          "    rc = -1;\n",
115          "  }\n",
116          "  xfree(v);\n",
117          "  return 0;\n",
118          "}\n\n");
119
120     # Asynchronous C API
121     # TODO
122
123     # Python API
124     # TODO
125
126     # Java API
127     # TODO
128 }
129
130 # TODO other command classes
131
132 # Front matter ----------------------------------------------------------------
133
134 our @gpl = ("/*\n",
135             " * This file is part of DisOrder.\n",
136             " * Copyright (C) 2010 Richard Kettlewell\n",
137             " *\n",
138             " * This program is free software: you can redistribute it and/or modify\n",
139             " * it under the terms of the GNU General Public License as published by\n",
140             " * the Free Software Foundation, either version 3 of the License, or\n",
141             " * (at your option) any later version.\n",
142             " *\n",
143             " * This program is distributed in the hope that it will be useful,\n",
144             " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
145             " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n",
146             " * GNU General Public License for more details.\n",
147             " *\n",
148             " * You should have received a copy of the GNU General Public License\n",
149             " * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n",
150             " */\n");
151
152
153 push(@h, @gpl,
154      "#ifndef CLIENT_STUBS_H\n",
155      "#define CLIENT_STUBS_H\n",
156      "\n");
157
158 push(@c, @gpl,
159      "\n");
160
161 # The protocol ----------------------------------------------------------------
162
163 simple("adopt",
164        "Adopt a track",
165        "Makes the calling user owner of a randomly picked track.",
166        [["id", "Track ID"]]);
167
168 simple("adduser",
169        "Create a user",
170        "Create a new user.  Requires the 'admin' right.  Email addresses etc must be filled in in separate commands.",
171        [["user", "New username"],
172         ["password", "Initial password"],
173         ["rights", "Initial rights (optional)"]]);
174
175 # TODO allfiles
176
177 simple("confirm",
178        "Confirm user registration",
179        "The confirmation string is as returned by the register command.",
180        [["confirmation", "Confirmnation string"]]);
181
182 # TODO cookie
183
184 simple("deluser",
185        "Delete user",
186        "Requires the 'admin' right.",
187        [["user", "User to delete"]]);
188
189 # TODO dirs
190
191 simple("disable",
192        "Disable play",
193        "Play will stop at the end of the current track, if one is playing.  Requires the 'global prefs' right.",
194        []);
195
196 simple("edituser",
197        "Set a user property",
198        "With the 'admin' right you can do anything.  Otherwise you need the 'userinfo' right and can only set 'email' and 'password'.",
199        [["username", "User to modify"],
200         ["property", "Property name"],
201         ["value", "New property value"]]);
202
203 simple("enable",
204        "Enable play",
205        "Requires the 'global prefs' right.",
206        []);
207
208 boolean("enabled",
209         "Detect whether play is enabled",
210         "",
211         [],
212         ["enabled", "1 if play is enabled and 0 otherwise"]);
213
214 boolean("exists",
215         "Test whether a track exists",
216         "",
217         [["track", "Track name"]],
218         ["exists", "1 if the track exists and 0 otherwise"]);
219
220 # TODO files
221
222 # TODO get
223
224 # TODO get-global
225
226 # TODO length
227
228 # TODO log
229
230 # TODO make-cookie
231
232 # TODO move
233
234 # TODO moveafter
235
236 # TODO new
237
238 simple("nop",
239        "Do nothing",
240        "Used as a keepalive.  No authentication required.",
241        []);
242
243 # TODO part
244
245 simple("pause",
246        "Pause the currently playing track",
247        "Requires the 'pause' right.",
248        []);
249
250 # TODO playafter
251
252 # TODO playing
253
254 simple("playlist-delete",
255        "Delete a playlist",
256        "Requires the 'play' right and permission to modify the playlist.",
257        [["playlist", "Playlist to delete"]]);
258
259 # TODO playlist-get
260
261 # TODO playlist-get-share
262
263 simple("playlist-lock",
264        "Lock a playlist",
265        "Requires the 'play' right and permission to modify the playlist.  A given connection may lock at most one playlist.",
266        [["playlist", "Playlist to delete"]]);
267
268 # TODO playlist-set
269
270 simple("playlist-set-share",
271        "Set a playlist's sharing status",
272        "Requires the 'play' right and permission to modify the playlist.  ",
273        [["playlist", "Playlist to modify"],
274         ["share", "New sharing status ('public', 'private' or 'shared')"]]);
275
276 simple("playlist-unlock",
277        "Unlock the locked playlist playlist",
278        "The playlist to unlock is implicit in the connection.",
279        []);
280
281 # TODO playlists
282
283 # TODO prefs
284
285 # TODO queue
286
287 simple("random-disable",
288        "Disable random play",
289        "Requires the 'global prefs' right.",
290        []);
291
292 simple("random-enable",
293        "Enable random play",
294        "Requires the 'global prefs' right.",
295        []);
296
297 boolean("random-enabled",
298         "Detect whether random play is enabled",
299         "Random play counts as enabled even if play is disabled.",
300         [],
301         ["enabled", "1 if random play is enabled and 0 otherwise"]);
302
303 # TODO random-enabled
304
305 # TODO recent
306
307 simple("reconfigure",
308        "Re-read configuraiton file.",
309        "Requires the 'admin' right.",
310        []);
311
312 # TODO register
313
314 simple("reminder",
315        "Send a password reminder.",
316        "If the user has no valid email address, or no password, or a reminder has been sent too recently, then no reminder will be sent.",
317        [["username", "User to remind"]]);
318
319 simple("remove",
320        "Remove a track form the queue.",
321        "Requires one of the 'remove mine', 'remove random' or 'remove any' rights depending on how the track came to be added to the queue.",
322        [["id", "Track ID"]]);
323
324 simple("rescan",
325        "Rescan all collections for new or obsolete tracks.",
326        "Requires the 'rescan' right.",
327        []);     # TODO wait/fresh flags
328
329 # TODO resolve
330
331 simple("resume",
332        "Resume the currently playing track",
333        "Requires the 'pause' right.",
334        []);
335
336 simple("revoke",
337        "Revoke a cookie.",
338        "It will not subsequently be possible to log in with the cookie.",
339        [["cookie", "Cookie to revoke"]]);
340
341 # TODO rtp-address
342
343 simple("scratch",
344        "Terminate the playing track.",
345        "Requires one of the 'scratch mine', 'scratch random' or 'scratch any' rights depending on how the track came to be added to the queue.",
346        [["id", "Track ID (optional)"]]);
347
348 # TODO schedule-add
349
350 simple("schedule-del",
351        "Delete a scheduled event.",
352        "Users can always delete their own scheduled events; with the admin right you can delete any event.",
353        [["event", "ID of event to delete"]]);
354
355 # TODO schedule-get
356
357 # TODO schedule-list
358
359 # TODO search
360
361 simple("set",
362        "Set a track preference",
363        "Requires the 'prefs' right.",
364        [["track", "Track name"],
365         ["pref", "Preference name"],
366         ["value", "New value"]]);
367
368 simple("set-global",
369        "Set a global preference",
370        "Requires the 'global prefs' right.",
371        [["pref", "Preference name"],
372         ["value", "New value"]]);
373
374 # TODO stats
375
376 # TODO tags
377
378 simple("unset",
379        "Unset a track preference",
380        "Requires the 'prefs' right.",
381        [["track", "Track name"],
382         ["pref", "Preference name"]]);
383
384 simple("unset-global",
385        "Set a global preference",
386        "Requires the 'global prefs' right.",
387        [["pref", "Preference name"]]);
388
389 # user is only used by connect functions
390
391 # TODO userinfo
392
393 # TODO users
394
395 # TODO version
396
397 # TODO volume
398
399 # End matter ------------------------------------------------------------------
400
401 push(@h, "#endif\n");
402
403 # Write it all out ------------------------------------------------------------
404
405 Write("client-stubs.h", \@h);
406 Write("client-stubs.c", \@c);