X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=recv.c;h=9d6f028319fc6e1e8f36f7406fc64475fb3576df;hp=13c5c420d35059d80fa25ba4e6c9cb73551f9b06;hb=fc8dfbb416ff07cca08fbf4e13efcaa25e17cc54;hpb=bb6b587015d2ccab90aa73664e8ad3c54c94b773 diff --git a/recv.c b/recv.c index 13c5c420..abebbfc2 100644 --- a/recv.c +++ b/recv.c @@ -1,128 +1,121 @@ /* - * Copyright (C) 2005-2006 Andre Noll + * Copyright (C) 2005 Andre Noll * - * 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, USA. + * Licensed under the GPL v2. For licencing details see COPYING. */ -#include "para.h" +/** \file recv.c the stand-alone audio stream receiver */ + +#include +#include +#include +#include + +#include "recv_cmd.lsg.h" +#include "para.h" +#include "list.h" +#include "sched.h" +#include "buffer_tree.h" #include "recv.h" #include "recv.cmdline.h" +#include "fd.h" +#include "string.h" #include "error.h" +#include "stdout.h" +#include "version.h" -struct gengetopt_args_info conf; +/** Array of error strings. */ +DEFINE_PARA_ERRLIST; -INIT_RECV_ERRLISTS; +/** The gengetopt args info struct. */ +static struct recv_args_info conf; -__printf_2_3 void para_log(int ll, char* fmt,...) -{ - va_list argp; - - /* ignore log message if loglevel is not high enough */ - if (ll < conf.loglevel_arg) - return; - va_start(argp, fmt); - vfprintf(stderr, fmt, argp); - va_end(argp); -} +static int loglevel; +/** Always log to stderr. */ +INIT_STDERR_LOGGING(loglevel); -static void *parse_config(int argc, char *argv[], int *receiver_num) +__noreturn static void print_help_and_die(void) { - int i; - - if (cmdline_parser(argc, argv, &conf)) - return NULL; - if (conf.list_receivers_given) { - printf("available receivers: "); - for (i = 0; receivers[i].name; i++) - printf("%s%s", i? " " : "", receivers[i].name); - printf("\nTry\n\tpara_recv -r ' -h'\n" - "for help on .\n"); - exit(EXIT_SUCCESS); - } - return check_receiver_arg(conf.receiver_arg, receiver_num); + bool d = conf.detailed_help_given; + if (d) + recv_cmdline_parser_print_detailed_help(); + else + recv_cmdline_parser_print_help(); + print_receiver_helps(d); + exit(EXIT_SUCCESS); } +/** + * The main function of para_recv. + * + * \param argc number of arguments + * \param argv vector of arguments + * + * para_recv uses the specified receiver to receive an audio stream sent by + * para_server. The received data is written to stdout. + * + * \return \a EXIT_SUCCESS on success, \a EXIT_FAILURE on errors. + */ int main(int argc, char *argv[]) { - int ret, eof = 0, max, r_opened = 0, receiver_num; - struct timeval timeout; - struct receiver *r = NULL; - fd_set rfds, wfds; + int ret; + bool r_opened = false; + const struct receiver *r = NULL; struct receiver_node rn; + struct stdout_task sot = {.btrn = NULL}; + static struct sched s; + struct task_info ti; + const struct lls_command *cmd; + struct lls_parse_result *receiver_lpr; /* receiver specific options */ + + recv_cmdline_parser(argc, argv, &conf); + loglevel = get_loglevel_by_name(conf.loglevel_arg); + version_handle_flag("recv", conf.version_given); + recv_init(); + if (conf.help_given || conf.detailed_help_given) + print_help_and_die(); memset(&rn, 0, sizeof(struct receiver_node)); - for (ret = 0; receivers[ret].name; ret++) - receivers[ret].init(&receivers[ret]); - ret = -E_RECV_SYNTAX; - rn.conf = parse_config(argc, argv, &receiver_num); - if (!rn.conf) { - PARA_EMERG_LOG("%s", "parse failed\n"); + ret = check_receiver_arg(conf.receiver_arg, &receiver_lpr); + if (ret < 0) goto out; - } - r = &receivers[receiver_num]; + cmd = lls_cmd(ret, recv_cmd_suite); + r = lls_user_data(cmd); rn.receiver = r; + rn.lpr = receiver_lpr; + rn.btrn = btr_new_node(&(struct btr_node_description) + EMBRACE(.name = lls_command_name(cmd))); ret = r->open(&rn); if (ret < 0) - goto out; - r_opened = 1; -recv: - FD_ZERO(&rfds); - FD_ZERO(&wfds); - timeout.tv_sec = 0; - timeout.tv_usec = 1000 * 1000; - max = -1; - ret = r->pre_select(&rn, &rfds, &wfds, &timeout); - max = MAX(max, ret); + goto free_receiver_lpr; + r_opened = true; - PARA_DEBUG_LOG("timeout: %lums\n", tv2ms(&timeout)); - ret = select(max + 1, &rfds, &wfds, NULL, &timeout); - if (ret < 0) { - if (errno == EINTR || errno == EAGAIN) - goto recv; - ret = -E_RECV_SELECT; - goto out; - } - ret = r->post_select(&rn, ret, &rfds, &wfds); - if (ret < 0) - goto out; - if (!ret) - eof = 1; - if (!rn.loaded) { - if (eof) - goto out; - goto recv; - } - ret = write(STDOUT_FILENO, rn.buf, rn.loaded); - PARA_DEBUG_LOG("wrote %d/%zd\n", ret, rn.loaded); - if (ret < 0) { - ret = -E_WRITE_STDOUT; - goto out; - } - if (ret != rn.loaded) { - PARA_INFO_LOG("short write %d/%zd\n", ret, rn.loaded); - memmove(rn.buf, rn.buf + ret, rn.loaded - ret); - } - rn.loaded -= ret; - if (rn.loaded || !eof) - goto recv; + sot.btrn = btr_new_node(&(struct btr_node_description) + EMBRACE(.parent = rn.btrn, .name = "stdout")); + stdout_task_register(&sot, &s); + + ti.name = lls_command_name(cmd); + ti.pre_select = r->pre_select; + ti.post_select = r->post_select; + ti.context = &rn; + rn.task = task_register(&ti, &s); + + s.default_timeout.tv_sec = 1; + s.default_timeout.tv_usec = 0; + ret = schedule(&s); + sched_shutdown(&s); + r->close(&rn); + btr_remove_node(&sot.btrn); + btr_remove_node(&rn.btrn); +free_receiver_lpr: + lls_free_parse_result(receiver_lpr, cmd); out: if (r_opened) r->close(&rn); - if (r) - r->shutdown(); + btr_remove_node(&rn.btrn); + btr_remove_node(&sot.btrn); + if (ret < 0) - PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); - return ret; + PARA_ERROR_LOG("%s\n", para_strerror(-ret)); + return ret < 0? EXIT_FAILURE : EXIT_SUCCESS; }