X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=play.c;h=1b3cc933926da62c9c6f6914759b66f015ac61ee;hp=cca203b5d393aa95dc50d0e7df1ffcceb0180420;hb=64cc9685a1bfa789dbcc447d68493691727e11ba;hpb=9c5fbc5dd8b53604d7e73fb6714ee2b5e3458866 diff --git a/play.c b/play.c index cca203b5..1b3cc933 100644 --- a/play.c +++ b/play.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Andre Noll + * Copyright (C) 2012 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -7,7 +7,6 @@ /** \file play.c Paraslash's standalone player. */ #include -#include #include #include @@ -58,7 +57,7 @@ enum state_change_request_type { }; struct play_task { - struct task task; + struct task *task; /* A bit array of invalid files (those will be skipped). */ bool *invalid; /* The file which is currently open. */ @@ -138,30 +137,14 @@ static void check_afh_receiver_or_die(void) exit(EXIT_FAILURE); } -/** Description to be included in the --detailed-help output. */ -#define PP_DESC \ -"para_play is a command line audio player.\n" \ -"\n" \ -"It operates either in command mode or in insert mode. In insert mode it\n" \ -"presents a prompt and allows to enter para_play commands like stop, play, pause\n" \ -"etc. In command mode, the current audio file is shown and the program reads\n" \ -"single key strokes from stdin. Keys may be mapped to para_play commands.\n" \ -"Whenever a mapped key is pressed, the associated command is executed.\n" \ - __noreturn static void print_help_and_die(void) { - int d = conf.detailed_help_given; - const char **p = d? play_args_info_detailed_help - : play_args_info_help; - -// printf_or_die("%s\n\n", PLAY_CMDLINE_PARSER_PACKAGE "-" -// PLAY_CMDLINE_PARSER_VERSION); - - printf_or_die("%s\n\n", play_args_info_usage); - if (d) - printf_or_die("%s\n", PP_DESC); - for (; *p; p++) - printf_or_die("%s\n", *p); + struct ggo_help help = DEFINE_GGO_HELP(play); + unsigned flags = conf.detailed_help_given? + GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS; + + ggo_print_help(&help, flags); + printf("supported audio formats: %s\n", AUDIO_FORMAT_HANDLERS); exit(0); } @@ -177,12 +160,11 @@ static void parse_config_or_die(int argc, char *argv[]) .print_errors = 1 }; - if (play_cmdline_parser_ext(argc, argv, &conf, ¶ms)) - exit(EXIT_FAILURE); - HANDLE_VERSION_FLAG("play", conf); + play_cmdline_parser_ext(argc, argv, &conf, ¶ms); + loglevel = get_loglevel_by_name(conf.loglevel_arg); + version_handle_flag("play", conf.version_given); if (conf.help_given || conf.detailed_help_given) print_help_and_die(); - loglevel = get_loglevel_by_name(conf.loglevel_arg); if (conf.config_file_given) config_file = para_strdup(conf.config_file_arg); else { @@ -199,12 +181,13 @@ static void parse_config_or_die(int argc, char *argv[]) params.initialize = 0; params.check_required = 1; play_cmdline_parser_config_file(config_file, &conf, ¶ms); + loglevel = get_loglevel_by_name(conf.loglevel_arg); } for (i = 0; i < conf.key_map_given; i++) { - char *s = strchr(conf.key_map_arg[i] + 1, ':'); - if (s) + char *kma = conf.key_map_arg[i]; + if (*kma && strchr(kma + 1, ':')) continue; - PARA_EMERG_LOG("invalid key map arg: %s\n", conf.key_map_arg[i]); + PARA_EMERG_LOG("invalid key map arg: %s\n", kma); goto err; } free(config_file); @@ -260,13 +243,16 @@ static void wipe_receiver_node(struct play_task *pt) /* returns: 0 not eof, 1: eof, < 0: fatal error. */ static int get_playback_error(struct play_task *pt) { - int err = pt->wn.task.error; + int err; + if (!pt->wn.task) + return 0; + err = task_status(pt->wn.task); if (err >= 0) return 0; - if (pt->fn.task.error >= 0) + if (task_status(pt->fn.task) >= 0) return 0; - if (pt->rn.task.error >= 0) + if (task_status(pt->rn.task) >= 0) return 0; if (err == -E_BTR_EOF || err == -E_RECV_EOF || err == -E_EOF || err == -E_WRITE_COMMON_EOF) @@ -284,16 +270,19 @@ static int eof_cleanup(struct play_task *pt) if (ret == 0) return ret; PARA_NOTICE_LOG("cleaning up wn/fn nodes\n"); + task_reap(&pt->wn.task); w->close(&pt->wn); btr_remove_node(&pt->wn.btrn); w->free_config(pt->wn.conf); memset(&pt->wn, 0, sizeof(struct writer_node)); + task_reap(&pt->fn.task); decoder->close(&pt->fn); btr_remove_node(&pt->fn.btrn); free(pt->fn.conf); memset(&pt->fn, 0, sizeof(struct filter_node)); + task_reap(&pt->rn.task); btr_remove_node(&pt->rn.btrn); /* * On eof (ret > 0), we do not wipe the receiver node struct until a @@ -312,7 +301,7 @@ static int shuffle_compare(__a_unused const void *a, __a_unused const void *b) static void shuffle(char **base, size_t num) { - srandom(now->tv_sec); + srandom(time(NULL)); qsort(base, num, sizeof(char *), shuffle_compare); } @@ -368,9 +357,6 @@ static int open_new_file(struct play_task *pt) free(tmp); tmp = NULL; } - pt->rn.task.pre_select = afh_recv->pre_select; - pt->rn.task.post_select = afh_recv->post_select; - sprintf(pt->rn.task.status, "%s receiver node", afh_recv->name); return 1; fail: wipe_receiver_node(pt); @@ -380,7 +366,7 @@ fail: static int load_file(struct play_task *pt) { const char *af; - char *tmp; + char *tmp, buf[20]; int ret; struct filter *decoder; @@ -390,7 +376,6 @@ static int load_file(struct play_task *pt) if (ret < 0) return ret; } else { - char buf[20]; pt->rn.btrn = new_recv_btrn(&pt->rn); sprintf(buf, "repos %lu", pt->start_chunk); ret = btr_exec_up(pt->rn.btrn, buf, &tmp); @@ -409,9 +394,6 @@ static int load_file(struct play_task *pt) goto fail; pt->fn.filter_num = ret; decoder = filters + ret; - pt->fn.task.pre_select = decoder->pre_select; - pt->fn.task.post_select = decoder->post_select; - sprintf(pt->fn.task.status, "%s decoder", af); pt->fn.btrn = btr_new_node(&(struct btr_node_description) EMBRACE(.name = decoder->name, .parent = pt->rn.btrn, .handler = decoder->execute, .context = &pt->fn)); @@ -419,11 +401,23 @@ static int load_file(struct play_task *pt) /* setup default writer */ pt->wn.conf = check_writer_arg_or_die(NULL, &pt->wn.writer_num); - pt->wn.task.error = 0; /* success, register tasks */ - register_task(&sched, &pt->rn.task); - register_task(&sched, &pt->fn.task); + pt->rn.task = task_register( + &(struct task_info) { + .name = afh_recv->name, + .pre_select = afh_recv->pre_select, + .post_select = afh_recv->post_select, + .context = &pt->rn + }, &sched); + sprintf(buf, "%s decoder", af); + pt->fn.task = task_register( + &(struct task_info) { + .name = buf, + .pre_select = decoder->pre_select, + .post_select = decoder->post_select, + .context = &pt->fn + }, &sched); register_writer_node(&pt->wn, pt->fn.btrn, &sched); return 1; fail: @@ -448,7 +442,7 @@ static int load_next_file(struct play_task *pt) int ret; again: - if (pt->rq == CRT_NONE || pt->rq == CRT_FILE_CHANGE) { + if (pt->rq == CRT_NONE) { pt->start_chunk = 0; ret = next_valid_file(pt); if (ret < 0) @@ -469,7 +463,8 @@ again: static void kill_stream(struct play_task *pt) { - task_notify(&pt->wn.task, E_EOF); + if (pt->wn.task) + task_notify(pt->wn.task, E_EOF); } #ifdef HAVE_READLINE @@ -638,23 +633,24 @@ static char **get_mapped_keyseqs(void) return result; } -#include "play_completion.h" +#include "play.command_list.h" +typedef int play_command_handler_t(struct play_task *, int, char**); +static play_command_handler_t PLAY_COMMAND_HANDLERS; /* defines one command of para_play */ struct pp_command { const char *name; - int (*handler)(struct play_task *, int, char**); + play_command_handler_t *handler; const char *description; const char *usage; const char *help; }; -#include "play_command_list.h" static struct pp_command pp_cmds[] = {DEFINE_PLAY_CMD_ARRAY}; #define FOR_EACH_COMMAND(c) for (c = 0; pp_cmds[c].name; c++) -#include "play_completion.h" +#include "play.completion.h" static struct i9e_completer pp_completers[]; I9E_DUMMY_COMPLETER(jmp); @@ -877,6 +873,7 @@ static int com_prev(struct play_task *pt, int argc, __a_unused char **argv) kill_stream(pt); pt->next_file = ret; pt->rq = CRT_FILE_CHANGE; + pt->start_chunk = 0; return 0; } @@ -892,6 +889,7 @@ static int com_next(struct play_task *pt, int argc, __a_unused char **argv) kill_stream(pt); pt->next_file = ret; pt->rq = CRT_FILE_CHANGE; + pt->start_chunk = 0; return 0; } @@ -991,15 +989,7 @@ out: static int play_i9e_line_handler(char *line) { - struct play_task *pt = &play_task; - int ret; - - if (line == NULL || !*line) - return 0; - ret = run_command(line, pt); - if (ret < 0) - return ret; - return 0; + return run_command(line, &play_task); } static int play_i9e_key_handler(int key) @@ -1045,7 +1035,7 @@ static void session_open(__a_unused struct play_task *pt) char *history_file; struct sigaction act; - PARA_NOTICE_LOG("\n%s\n", VERSION_TEXT("play")); + PARA_NOTICE_LOG("\n%s\n", version_text("play")); if (conf.history_file_given) history_file = para_strdup(conf.history_file_arg); else { @@ -1108,9 +1098,8 @@ static void session_update_time_string(struct play_task *pt, char *str, unsigned * terminates. Subsequent calls to i9e_get_error() then return negative and we * are allowed to call i9e_close() and terminate as well. */ -static int session_post_select(__a_unused struct sched *s, struct task *t) +static int session_post_select(__a_unused struct sched *s, struct play_task *pt) { - struct play_task *pt = container_of(t, struct play_task, task); int ret; if (pt->background) @@ -1132,9 +1121,8 @@ static int session_post_select(__a_unused struct sched *s, struct task *t) #else /* HAVE_READLINE */ -static int session_post_select(struct sched *s, struct task *t) +static int session_post_select(struct sched *s, struct play_task *pt) { - struct play_task *pt = container_of(t, struct play_task, task); char c; if (!FD_ISSET(STDIN_FILENO, &s->rfds)) @@ -1157,9 +1145,9 @@ static void session_update_time_string(__a_unused struct play_task *pt, } #endif /* HAVE_READLINE */ -static void play_pre_select(struct sched *s, struct task *t) +static void play_pre_select(struct sched *s, void *context) { - struct play_task *pt = container_of(t, struct play_task, task); + struct play_task *pt = context; char state; para_fd_set(STDIN_FILENO, &s->rfds, &s->max_fileno); @@ -1196,17 +1184,17 @@ static unsigned get_time_string(struct play_task *pt, char **result) ); } -static void play_post_select(struct sched *s, struct task *t) +static int play_post_select(struct sched *s, void *context) { - struct play_task *pt = container_of(t, struct play_task, task); + struct play_task *pt = context; int ret; ret = eof_cleanup(pt); if (ret < 0) { pt->rq = CRT_TERM_RQ; - return; + return 0; } - ret = session_post_select(s, t); + ret = session_post_select(s, pt); if (ret < 0) goto out; if (!pt->wn.btrn && !pt->fn.btrn) { @@ -1234,7 +1222,7 @@ static void play_post_select(struct sched *s, struct task *t) } ret = 1; out: - t->error = ret; + return ret; } /** @@ -1255,7 +1243,6 @@ int main(int argc, char *argv[]) filter_init(); writer_init(); - gettimeofday(now, NULL); sched.default_timeout.tv_sec = 5; parse_config_or_die(argc, argv); @@ -1270,11 +1257,14 @@ int main(int argc, char *argv[]) pt->rq = CRT_FILE_CHANGE; pt->current_file = conf.inputs_num - 1; pt->playing = true; - pt->task.pre_select = play_pre_select; - pt->task.post_select = play_post_select; - sprintf(pt->task.status, "play task"); - register_task(&sched, &pt->task); + pt->task = task_register(&(struct task_info){ + .name = "play", + .pre_select = play_pre_select, + .post_select = play_post_select, + .context = pt, + }, &sched); ret = schedule(&sched); + sched_shutdown(&sched); if (ret < 0) PARA_ERROR_LOG("%s\n", para_strerror(-ret)); return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;