#! /usr/bin/perl -w
#
# This file is part of DisOrder.
-# Copyright (C) 2010 Richard Kettlewell
+# Copyright (C) 2010-11 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
# boolean True or false. "yes" or "no" on the wire.
# list In commands: a list of strings in the command.
# In returns: a list of lines in the response.
+# pair-list In returns: a list of key-value pairs in a response body.
# body In commands: a list of strings as a command body.
# In returns: a list of strings as a response body.
# queue In returns: a list of queue entries in a response body.
our @h = ();
our @c = ();
+# Write(PATH, LINES)
+#
+# Write array ref LINES to file PATH.
sub Write {
my $path = shift;
my $lines = shift;
# Command classes -------------------------------------------------------------
+# c_in_decl([TYPE, NAME])
+#
+# Return the C declaration for an input parameter of type TYPE with
+# name NAME.
sub c_in_decl {
my $arg = shift;
}
}
+# c_out_decl([TYPE, NAME])
+#
+# Return the C declaration for an output (reference) parameter of type
+# TYPE with name NAME.
sub c_out_decl {
my $arg = shift;
} elsif($type eq 'list' or $type eq 'body') {
return ("char ***${name}p",
"int *n${name}p");
+ } elsif($type eq 'pair-list') {
+ return ("struct kvp **${name}p");
} elsif($type eq 'queue' or $type eq 'queue-one') {
return ("struct queue_entry **${name}p");
} elsif($type eq 'user') {
}
}
+# c_param_docs([TYPE, NAME})
+#
+# Return the doc string for a C input parameter.
sub c_param_docs {
my $args = shift;
my @d = ();
return @d;
}
+# c_param_docs([TYPE, NAME})
+#
+# Return the doc string for a C output parameter.
sub c_return_docs {
my $return = shift;
return () unless defined $return;
} elsif($type eq 'list' or $type eq 'body') {
return (" * \@param ${name}p $descr\n",
" * \@param n${name}p Number of elements in ${name}p\n");
+ } elsif($type eq 'pair-list') {
+ return (" * \@param ${name}p $descr\n");
} elsif($type eq 'queue' or $type eq 'queue-one') {
return (" * \@param ${name}p $descr\n");
} elsif($type eq 'user') {
# simple(CMD, SUMMARY, DETAIL,
# [[TYPE,NAME,DESCR], [TYPE,NAME,DESCR], ...],
# [RETURN-TYPE, RETURN-NAME, RETURN_DESCR])
+#
+# CMD is normally just the name of the command, but can
+# be [COMMAND,FUNCTION] if the function name should differ
+# from the protocol command.
sub simple {
my $cmd = shift;
my $summary = shift;
my $args = shift;
my $return = shift;
+ my $cmdc;
+ if(ref $cmd eq 'ARRAY') {
+ $cmdc = $$cmd[1];
+ $cmd = $$cmd[0];
+ } else {
+ $cmdc = $cmd;
+ $cmdc =~ s/-/_/g;
+ }
print STDERR "Processing $cmd... ";
- my $cmdc = $cmd;
- $cmdc =~ s/-/_/g;
# Synchronous C API
print STDERR "H ";
push(@h, "/** \@brief $summary\n",
map(c_in_decl($_), @$args),
c_out_decl($return)),
") {\n");
+ my @cargs = ();
+ for my $arg (@$args) {
+ if($arg->[0] eq 'body' or $arg->[0] eq 'list') {
+ push(@cargs, "disorder_$arg->[0]", $arg->[1], "n$arg->[1]");
+ } elsif($arg->[0] eq 'string') {
+ push(@cargs, $arg->[1]);
+ } elsif($arg->[0] eq 'integer') {
+ push(@cargs, "buf_$arg->[1]");
+ push(@c, " char buf_$arg->[1]\[16];\n",
+ " byte_snprintf(buf_$arg->[1], sizeof buf_$arg->[1], \"%ld\", $arg->[1]);\n");
+ } else {
+ die "$0: unsupported arg type '$arg->[0]' for '$cmd'\n";
+ }
+ }
if(!defined $return) {
- my @cargs = ();
- for my $arg (@$args) {
- if($arg->[0] eq 'body' or $arg->[0] eq 'list') {
- push(@cargs, "disorder_$arg->[0]", $arg->[1], "n$arg->[1]");
- } elsif($arg->[0] eq 'string') {
- push(@cargs, $arg->[1]);
- } elsif($arg->[0] eq 'integer') {
- push(@cargs, "buf_$arg->[1]");
- push(@c, " char buf_$arg->[1]\[16];\n",
- " byte_snprintf(buf_$arg->[1], sizeof buf_$arg->[1], \"%ld\", $arg->[1]);\n");
- } else {
- die "$0: unsupported arg type '$arg->[0]' for '$cmd'\n";
- }
- }
push(@c, " return disorder_simple(",
join(", ", "c", 0, "\"$cmd\"", @cargs, "(char *)0"),
");\n");
} elsif($return->[0] eq 'string') {
- push(@c, " return dequote(disorder_simple(c, $return->[1]p, \"$cmd\"",
- map(", $_->[1]", @$args),
- ", (char *)0), $return->[1]p);\n");
+ push(@c, " return dequote(disorder_simple(",
+ join(", ", "c", "$return->[1]p", "\"$cmd\"",
+ @cargs,
+ "(char *)0"),
+ "), $return->[1]p);\n");
} elsif($return->[0] eq 'boolean') {
push(@c, " char *v;\n",
" int rc;\n",
- " if((rc = disorder_simple(c, &v, \"$cmd\"",
- map(", $_->[1]", @$args),
- ", (char *)0)))\n",
+ " if((rc = disorder_simple(",
+ join(", ", "c", "&v", "\"$cmd\"",
+ @cargs,
+ "(char *)0"),
+ ")))\n",
" return rc;\n",
" return boolean(\"$cmd\", v, $return->[1]p);\n");
} elsif($return->[0] eq 'integer') {
push(@c, " char *v;\n",
" int rc;\n",
"\n",
- " if((rc = disorder_simple(c, &v, \"$cmd\"",
- map(", $_->[1]", @$args),
- ", (char *)0)))\n",
+ " if((rc = disorder_simple(",
+ join(", ", "c", "&v", "\"$cmd\"",
+ @cargs,
+ "(char *)0"),
+ ")))\n",
" return rc;\n",
" *$return->[1]p = atol(v);\n",
" xfree(v);\n",
} elsif($return->[0] eq 'user') {
push(@c, " char *u;\n",
" int rc;\n",
- " if((rc = disorder_simple(c, &u, \"$cmd\"",
- map(", $_->[1]", @$args),
- " )))\n",
+ " if((rc = disorder_simple(",
+ join(", ", "c", "&u", "\"$cmd\"",
+ @cargs, "(char *)0"),
+ ")))\n",
" return rc;\n",
" c->user = u;\n",
" return 0;\n");
} elsif($return->[0] eq 'body') {
- push(@c, " return disorder_simple_list(c, $return->[1]p, n$return->[1]p, \"$cmd\"",
- map(", $_->[1]", @$args),
- ", (char *)0);\n");
+ push(@c, " return disorder_simple_list(",
+ join(", ", "c", "$return->[1]p", "n$return->[1]p", "\"$cmd\"",
+ @cargs,
+ "(char *)0"),
+ ");\n");
} elsif($return->[0] eq 'queue') {
push(@c, " return somequeue(c, \"$cmd\", $return->[1]p);\n");
} elsif($return->[0] eq 'queue-one') {
push(@c, " return onequeue(c, \"$cmd\", $return->[1]p);\n");
+ } elsif($return->[0] eq 'pair-list') {
+ push(@c, " return pairlist(",
+ join(", ", "c", "$return->[1]p", "\"$cmd\"",
+ @cargs,
+ "(char *)0"),
+ ");\n");
} else {
die "$0: C API: unknown type '$return->[0]' for '$cmd'\n";
}
# Front matter ----------------------------------------------------------------
+our @generated = ("/*\n",
+ " * Automatically generated file, see scripts/protocol\n",
+ " *\n",
+ " * DO NOT EDIT.\n",
+ " */\n");
+
our @gpl = ("/*\n",
" * This file is part of DisOrder.\n",
- " * Copyright (C) 2010 Richard Kettlewell\n",
+ " * Copyright (C) 2010-11 Richard Kettlewell\n",
" *\n",
" * This program is free software: you can redistribute it and/or modify\n",
" * it under the terms of the GNU General Public License as published by\n",
" */\n");
-push(@h, @gpl,
+push(@h, @generated, @gpl,
"#ifndef CLIENT_STUBS_H\n",
"#define CLIENT_STUBS_H\n",
"\n");
-push(@c, @gpl,
+push(@c, @generated, @gpl,
"\n");
# The protocol ----------------------------------------------------------------
[["string", "target", "Move after this track, or to head if \"\""],
["list", "ids", "List of tracks to move by ID"]]);
-# TODO new
+simple(["new", "new_tracks"],
+ "List recently added tracks",
+ "",
+ [["integer", "max", "Maximum tracks to fetch, or 0 for all available"]],
+ ["body", "tracks", "Recently added tracks"]);
simple("nop",
"Do nothing",
[],
["body", "playlists", "Playlist names"]);
-# TODO prefs
+simple("prefs",
+ "Get all the preferences for a track",
+ "",
+ [["string", "track", "Track name"]],
+ ["pair-list", "prefs", "Track preferences"]);
simple("queue",
"List the queue",
"Users can always delete their own scheduled events; with the admin right you can delete any event.",
[["string", "event", "ID of event to delete"]]);
-# TODO schedule-get
+simple("schedule-get",
+ "Get the details of scheduled event",
+ "",
+ [["string", "id", "Event ID"]],
+ ["pair-list", "actiondata", "Details of event"]);
simple("schedule-list",
"List scheduled events",