X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod_command.c;h=cb4363b15bc12507af12c07ed0d0f3978da2ac55;hp=3a39027523a72c686d997d1b358912dc5dfd2363;hb=bb1996d4ef04bf33e735f2ce49e9edeeb5a66e80;hpb=904e302f0b64887f18c9e2fec7b0bb405675ad22 diff --git a/audiod_command.c b/audiod_command.c index 3a390275..cb4363b1 100644 --- a/audiod_command.c +++ b/audiod_command.c @@ -1,8 +1,4 @@ -/* - * Copyright (C) 2005 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2005 Andre Noll , see file COPYING. */ /** \file audiod_command.c Commands for para_audiod. */ @@ -13,13 +9,13 @@ #include #include #include +#include +#include "audiod.lsg.h" #include "para.h" -#include "audiod.cmdline.h" -#include "audiod.command_list.h" +#include "audiod_cmd.lsg.h" #include "list.h" #include "sched.h" -#include "ggo.h" #include "buffer_tree.h" #include "filter.h" #include "grab_client.h" @@ -35,35 +31,23 @@ extern struct sched sched; extern char *stat_item_values[NUM_STAT_ITEMS]; -typedef int audiod_command_handler_t(int, int, char **); -static audiod_command_handler_t AUDIOD_COMMAND_HANDLERS; - -/* Defines one command of para_audiod. */ -struct audiod_command { - const char *name; - /* Pointer to the function that handles the command. */ - /* - * Command handlers must never never close their file descriptor. A - * positive return value tells audiod that the status items have - * changed. In this case audiod will send an updated version of all - * status items to to each connected stat client. - */ - audiod_command_handler_t *handler; - /* One-line description. */ - const char *description; - /* Summary of the command line options. */ - const char *usage; - /* The long help text. */ - const char *help; -}; +/** The maximal number of simultaneous connections. */ +#define MAX_STAT_CLIENTS 50 -static struct audiod_command audiod_cmds[] = {DEFINE_AUDIOD_CMD_ARRAY}; +/** Pointer to a command handler function. */ +typedef int (*audiod_cmd_handler_t)(int, struct lls_parse_result *); -/** Iterate over the array of all audiod commands. */ -#define FOR_EACH_COMMAND(c) for (c = 0; audiod_cmds[c].name; c++) +/** The lopsub user_data pointer. Only the command handler at the moment. */ +struct audiod_command_info { + audiod_cmd_handler_t handler; /**< Implementation of the command. */ +}; -/** The maximal number of simultaneous connections. */ -#define MAX_STAT_CLIENTS 50 +/** Define the user_data pointer as expected by lopsub. */ +#define EXPORT_AUDIOD_CMD_HANDLER(_cmd) \ + /** Implementation of _cmd. */ \ + const struct audiod_command_info lsg_audiod_cmd_com_ ## _cmd ## _user_data = { \ + .handler = com_ ## _cmd \ + }; /** Flags used for the stat command of para_audiod. */ enum stat_client_flags { @@ -94,7 +78,7 @@ static INITIALIZED_LIST_HEAD(client_list); static int num_clients; /** The list of all status items used by para_{server,audiod,gui}. */ -const char *status_item_list[] = {STATUS_ITEM_ARRAY}; +const char *status_item_list[] = {STATUS_ITEMS}; static void dump_stat_client_list(void) { @@ -245,10 +229,11 @@ static int dump_commands(int fd) char *buf = para_strdup(""), *tmp = NULL; int i; ssize_t ret; + const struct lls_command *cmd; - FOR_EACH_COMMAND(i) { - tmp = make_message("%s%s\t%s\n", buf, audiod_cmds[i].name, - audiod_cmds[i].description); + for (i = 1; (cmd = lls_cmd(i, audiod_cmd_suite)); i++) { + tmp = make_message("%s%s\t%s\n", buf, lls_command_name(cmd), + lls_purpose(cmd)); free(buf); buf = tmp; } @@ -257,76 +242,80 @@ static int dump_commands(int fd) return ret; } -static int com_help(int fd, int argc, char **argv) +static int com_help(int fd, struct lls_parse_result *lpr) { - int i, ret; - char *buf; - - if (argc < 2) { - ret = dump_commands(fd); - goto out; + int ret; + char *buf, *errctx; + const struct lls_command *cmd; + + ret = lls(lls_check_arg_count(lpr, 0, 1, &errctx)); + if (ret < 0) { + if (errctx) { + buf = make_message("%s\n", errctx); + client_write(fd, buf); + free(buf); + free(errctx); + } + return ret; } - FOR_EACH_COMMAND(i) { - if (strcmp(audiod_cmds[i].name, argv[1])) - continue; - buf = make_message( - "NAME\n\t%s -- %s\n" - "SYNOPSIS\n\tpara_audioc %s\n" - "DESCRIPTION\n%s\n", - argv[1], - audiod_cmds[i].description, - audiod_cmds[i].usage, - audiod_cmds[i].help - ); - ret = client_write(fd, buf); + if (lls_num_inputs(lpr) == 0) + return dump_commands(fd); + ret = lls(lls_lookup_subcmd(lls_input(0, lpr), audiod_cmd_suite, + &errctx)); + if (ret < 0) { + buf = make_message("%s: %s\nAvailable commands:\n", errctx? + errctx : lls_input(0, lpr), para_strerror(-ret)); + if (client_write(fd, buf) >= 0) + dump_commands(fd); + free(errctx); free(buf); goto out; } - ret = client_write(fd, "No such command. Available commands:\n"); - if (ret > 0) - ret = dump_commands(fd); + cmd = lls_cmd(ret, audiod_cmd_suite); + buf = lls_long_help(cmd); + assert(buf); + ret = client_write(fd, buf); + free(buf); out: return ret < 0? ret : 0; } +EXPORT_AUDIOD_CMD_HANDLER(help) -static int com_tasks(int fd, __a_unused int argc, __a_unused char **argv) +static int com_tasks(int fd, __a_unused struct lls_parse_result *lpr) { + int ret; char *tl = get_task_list(&sched); - int ret = 1; - if (tl) - ret = client_write(fd, tl); + if (!tl) /* no tasks registered yet */ + return 0; + ret = client_write(fd, tl); free(tl); - return ret < 0? ret : 0; + return ret; } +EXPORT_AUDIOD_CMD_HANDLER(tasks) -static int com_stat(int fd, int argc, char **argv) +static int com_stat(int fd, struct lls_parse_result *lpr) { int i, ret, parser_friendly = 0; uint64_t mask = 0; const uint64_t one = 1; struct para_buffer b = {.flags = 0}; + const struct lls_opt_result *r; + unsigned num_inputs; ret = mark_fd_nonblocking(fd); if (ret < 0) return ret; - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - if (arg[0] != '-') - break; - if (!strcmp(arg, "--")) { - i++; - break; - } - if (!strncmp(arg, "-p", 2)) { - parser_friendly = 1; - b.flags = PBF_SIZE_PREFIX; - } + r = lls_opt_result(LSG_AUDIOD_CMD_STAT_OPT_PARSER_FRIENDLY, lpr); + if (lls_opt_given(r) > 0) { + parser_friendly = 1; + b.flags = PBF_SIZE_PREFIX; } - if (i >= argc) + num_inputs = lls_num_inputs(lpr); + if (num_inputs == 0) mask--; /* set all bits */ - for (; i < argc; i++) { - ret = stat_item_valid(argv[i]); + for (i = 0; i < num_inputs; i++) { + ret = stat_item_valid(lls_input(i, lpr)); if (ret < 0) return ret; mask |= (one << ret); @@ -344,58 +333,61 @@ static int com_stat(int fd, int argc, char **argv) free(b.buf); return ret < 0? ret : 0; } +EXPORT_AUDIOD_CMD_HANDLER(stat) -static int com_grab(int fd, int argc, char **argv) +static int com_grab(int fd, struct lls_parse_result *lpr) { - int ret = grab_client_new(fd, argc, argv, &sched); + int ret = grab_client_new(fd, lpr, &sched); return ret < 0? ret : 0; } +EXPORT_AUDIOD_CMD_HANDLER(grab) -static int com_term(__a_unused int fd, __a_unused int argc, __a_unused char **argv) +static int com_term(__a_unused int fd, __a_unused struct lls_parse_result *lpr) { return -E_AUDIOD_TERM; } +EXPORT_AUDIOD_CMD_HANDLER(term) -static int com_on(__a_unused int fd, __a_unused int argc, __a_unused char **argv) +static int com_on(__a_unused int fd, __a_unused struct lls_parse_result *lpr) { audiod_status = AUDIOD_ON; return 1; } +EXPORT_AUDIOD_CMD_HANDLER(on) -static int com_off(__a_unused int fd, __a_unused int argc, __a_unused char **argv) +static int com_off(__a_unused int fd, __a_unused struct lls_parse_result *lpr) { audiod_status = AUDIOD_OFF; return 1; } +EXPORT_AUDIOD_CMD_HANDLER(off) -static int com_sb(__a_unused int fd, __a_unused int argc, __a_unused char **argv) +static int com_sb(__a_unused int fd, __a_unused struct lls_parse_result *lpr) { audiod_status = AUDIOD_STANDBY; return 1; } +EXPORT_AUDIOD_CMD_HANDLER(sb) -static int com_cycle(__a_unused int fd, int argc, char **argv) +static int com_cycle(__a_unused int fd, __a_unused struct lls_parse_result *lpr) { switch (audiod_status) { - case AUDIOD_ON: - return com_sb(fd, argc, argv); - break; - case AUDIOD_OFF: - return com_on(fd, argc, argv); - break; - case AUDIOD_STANDBY: - return com_off(fd, argc, argv); - break; + case AUDIOD_ON: audiod_status = AUDIOD_STANDBY; break; + case AUDIOD_OFF: audiod_status = AUDIOD_ON; break; + case AUDIOD_STANDBY: audiod_status = AUDIOD_OFF; break; } return 1; } +EXPORT_AUDIOD_CMD_HANDLER(cycle) -static int com_version(int fd, int argc, char **argv) +static int com_version(int fd, struct lls_parse_result *lpr) { int ret; char *msg; + const struct lls_opt_result *r_v; - if (argc > 1 && strcmp(argv[1], "-v") == 0) + r_v = lls_opt_result(LSG_AUDIOD_CMD_VERSION_OPT_VERBOSE, lpr); + if (lls_opt_given(r_v)) msg = make_message("%s", version_text("audiod")); else msg = make_message("%s\n", version_single_line("audiod")); @@ -403,6 +395,7 @@ static int com_version(int fd, int argc, char **argv) free(msg); return ret < 0? ret : 0; } +EXPORT_AUDIOD_CMD_HANDLER(version) /** * Handle arriving connections on the local socket. @@ -419,14 +412,18 @@ static int com_version(int fd, int argc, char **argv) * \return Positive on success, negative on errors, zero if there was no * connection to accept. * - * \sa para_accept(), recv_cred_buffer() + * \sa \ref para_accept(), \ref recv_cred_buffer(). * */ int handle_connect(int accept_fd, fd_set *rfds) { - int i, argc, ret, clifd; + int argc, ret, clifd; char buf[MAXLINE], **argv = NULL; struct sockaddr_un unix_addr; uid_t uid; + const struct lls_command *cmd; + struct lls_parse_result *lpr; + char *errctx = NULL; + const struct audiod_command_info *aci; ret = para_accept(accept_fd, rfds, &unix_addr, sizeof(struct sockaddr_un), &clifd); if (ret <= 0) @@ -443,18 +440,27 @@ int handle_connect(int accept_fd, fd_set *rfds) if (ret <= 0) goto out; argc = ret; - //PARA_INFO_LOG("argv[0]: %s, argc = %d\n", argv[0], argc); - FOR_EACH_COMMAND(i) { - if (strcmp(audiod_cmds[i].name, argv[0])) - continue; - ret = audiod_cmds[i].handler(clifd, argc, argv); + ret = lls(lls_lookup_subcmd(argv[0], audiod_cmd_suite, &errctx)); + if (ret < 0) goto out; - } - ret = -E_INVALID_AUDIOD_CMD; + cmd = lls_cmd(ret, audiod_cmd_suite); + ret = lls(lls_parse(argc, argv, cmd, &lpr, &errctx)); + if (ret < 0) + goto out; + aci = lls_user_data(cmd); + ret = aci->handler(clifd, lpr); + lls_free_parse_result(lpr, cmd); out: free_argv(argv); if (ret < 0 && ret != -E_CLIENT_WRITE) { - char *tmp = make_message("%s\n", para_strerror(-ret)); + char *tmp; + if (errctx) { + tmp = make_message("%s\n", errctx); + free(errctx); + client_write(clifd, tmp); + free(tmp); + } + tmp = make_message("%s\n", para_strerror(-ret)); client_write(clifd, tmp); free(tmp); } @@ -471,41 +477,41 @@ void audiod_status_dump(bool force) { char *old, *new; - old = stat_item_values[SI_PLAY_TIME]; + old = stat_item_values[SI_play_time]; new = get_time_string(); if (new) { if (force || !old || strcmp(old, new)) { free(old); - stat_item_values[SI_PLAY_TIME] = new; - stat_client_write_item(SI_PLAY_TIME); + stat_item_values[SI_play_time] = new; + stat_client_write_item(SI_play_time); } else free(new); } new = daemon_get_uptime_str(now); - old = stat_item_values[SI_AUDIOD_UPTIME]; + old = stat_item_values[SI_audiod_uptime]; if (force || !old || strcmp(old, new)) { free(old); - stat_item_values[SI_AUDIOD_UPTIME] = new; - stat_client_write_item(SI_AUDIOD_UPTIME); + stat_item_values[SI_audiod_uptime] = new; + stat_client_write_item(SI_audiod_uptime); } else free(new); - old = stat_item_values[SI_AUDIOD_STATUS]; + old = stat_item_values[SI_audiod_status]; new = audiod_status_string(); if (force || !old || strcmp(old, new)) { free(old); - stat_item_values[SI_AUDIOD_STATUS] = new; - stat_client_write_item(SI_AUDIOD_STATUS); + stat_item_values[SI_audiod_status] = new; + stat_client_write_item(SI_audiod_status); } else free(new); - old = stat_item_values[SI_DECODER_FLAGS]; + old = stat_item_values[SI_decoder_flags]; new = audiod_get_decoder_flags(); if (force || !old || strcmp(old, new)) { free(old); - stat_item_values[SI_DECODER_FLAGS] = new; - stat_client_write_item(SI_DECODER_FLAGS); + stat_item_values[SI_decoder_flags] = new; + stat_client_write_item(SI_decoder_flags); } else free(new); }