X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=play.c;h=c9a9f7d7e8a69a0d2db51d3fdbdc8e04aec1c6d7;hb=refs%2Fheads%2Fpu;hp=4f734a3f729c526b8b319edbf2a477c636e2abe6;hpb=d955fb7bc5640767c14560e06e6f9c47d3cb49c5;p=paraslash.git diff --git a/play.c b/play.c index 4f734a3f..5b20315a 100644 --- a/play.c +++ b/play.c @@ -570,15 +570,17 @@ static inline char *get_internal_key_map_seq(int key) return para_strdup(default_keyseqs[get_internal_key_map_idx(key)]); } -static char *get_user_key_map_seq(int key) +static char *get_key_map_seq(int key) { - const char *kma = get_user_key_map_arg(key); - const char *p = strchr(kma + 1, ':'); + const char *kma, *p; char *result; int len; - if (!p) - return NULL; + if (is_internal_key(key)) + return get_internal_key_map_seq(key); + kma = get_user_key_map_arg(key); + p = strchr(kma + 1, ':'); + assert(p); /* We checked earlier that kma contains a colon */ len = p - kma; result = alloc(len + 1); memcpy(result, kma, len); @@ -586,12 +588,6 @@ static char *get_user_key_map_seq(int key) return result; } -static char *get_key_map_seq(int key) -{ - return is_internal_key(key)? - get_internal_key_map_seq(key) : get_user_key_map_seq(key); -} - static char *get_key_map_seq_safe(int key) { const char hex[] = "0123456789abcdef"; @@ -915,7 +911,7 @@ static int com_jmp(struct lls_parse_result *lpr) return com_next(NULL); if (pt->playing && !pt->fn.btrn) return 0; - pt->start_chunk = percent * pt->num_chunks / 100; + pt->start_chunk = (uint64_t)percent * pt->num_chunks / 100; if (!pt->playing) return 0; pt->rq = CRT_REPOS; @@ -945,7 +941,7 @@ static int com_ff(struct lls_parse_result *lpr) seconds += (get_play_time() + 500) / 1000; seconds = PARA_MIN(seconds, (typeof(seconds))pt->seconds - 4); seconds = PARA_MAX(seconds, 0); - pt->start_chunk = pt->num_chunks * seconds / pt->seconds; + pt->start_chunk = (uint64_t)pt->num_chunks * seconds / pt->seconds; pt->start_chunk = PARA_MIN(pt->start_chunk, pt->num_chunks - 1); pt->start_chunk = PARA_MAX(pt->start_chunk, 0UL); if (!pt->playing) @@ -1041,17 +1037,14 @@ static void session_open(void) if (OPT_GIVEN(HISTORY_FILE)) history_file = para_strdup(OPT_STRING_VAL(HISTORY_FILE)); else { - char *home = para_homedir(); - char *dot_para = make_message("%s/.paraslash", home); + const char *confdir = get_confdir(); - free(home); - ret = para_mkdir(dot_para); + ret = para_mkdir(confdir); /* warn, but otherwise ignore mkdir error */ if (ret < 0) - PARA_WARNING_LOG("Can not create %s: %s\n", dot_para, + PARA_WARNING_LOG("Can not create %s: %s\n", confdir, para_strerror(-ret)); - history_file = make_message("%s/play.history", dot_para); - free(dot_para); + history_file = make_message("%s/play.history", confdir); } ici.history_file = history_file; ici.loglevel = loglevel; @@ -1095,39 +1088,6 @@ static void session_update_time_string(char *str, unsigned len) i9e_print_status_bar(str, len); } -/* - * If we are about to die we must call i9e_close() to reset the terminal. - * However, i9e_close() must be called in *this* context, i.e. from - * play_task.post_monitor() rather than from i9e_post_monitor(), because - * otherwise i9e would access freed memory upon return. So the play task must - * stay alive until the i9e task terminates. - * - * We achieve this by sending a fake SIGTERM signal via i9e_signal_dispatch() - * and reschedule. In the next iteration, i9e->post_monitor returns an error and - * 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_monitor(__a_unused struct sched *s) -{ - int ret; - - if (pt->background) - detach_stdout(); - else - attach_stdout(__FUNCTION__); - ret = i9e_get_error(); - if (ret < 0) { - kill_stream(); - i9e_close(); - para_log = stderr_log; - free(ici.history_file); - return ret; - } - if (get_playback_state() == 'X') - i9e_signal_dispatch(SIGTERM); - return 0; -} - static void play_pre_monitor(struct sched *s, __a_unused void *context) { char state; @@ -1166,18 +1126,24 @@ static unsigned get_time_string(char **result) ); } -static int play_post_monitor(struct sched *s, __a_unused void *context) +static int play_post_monitor(__a_unused struct sched *s, __a_unused void *context) { - int ret; + int ret, i9e_error; + if (pt->background) + detach_stdout(); + else + attach_stdout(__FUNCTION__); + i9e_error = i9e_get_error(); ret = eof_cleanup(); - if (ret < 0) { - pt->rq = CRT_TERM_RQ; - return 0; - } - ret = session_post_monitor(s); - if (ret < 0) - goto out; + if (pt->rq == CRT_TERM_RQ || i9e_error < 0) /* com_quit() or CTRL+D */ + kill_stream(); /* terminate receiver/filter/writer */ + if ((ret < 0 || pt->rq == CRT_TERM_RQ) && i9e_error >= 0) + i9e_signal_dispatch(SIGTERM); /* terminate the i9e task */ + if (ret < 0) /* unexpected error from the writer node */ + return ret; + if (ret != 0 && i9e_error < 0) /* eof, and i9e has died */ + return i9e_error; if (!pt->wn.btrn && !pt->fn.btrn) { char state = get_playback_state(); if (state == 'P' || state == 'R' || state == 'F') { @@ -1186,8 +1152,7 @@ static int play_post_monitor(struct sched *s, __a_unused void *context) if (ret < 0) { PARA_ERROR_LOG("%s\n", para_strerror(-ret)); pt->rq = CRT_TERM_RQ; - ret = 1; - goto out; + return 1; } pt->next_update = *now; } @@ -1201,9 +1166,7 @@ static int play_post_monitor(struct sched *s, __a_unused void *context) free(str); tv_add(now, &delay, &pt->next_update); } - ret = 1; -out: - return ret; + return 1; } /** @@ -1250,7 +1213,12 @@ int main(int argc, char *argv[]) }, &sched); ret = schedule(&sched); sched_shutdown(&sched); + i9e_close(); + wipe_receiver_node(); + para_log = stderr_log; + free(ici.history_file); if (ret < 0) PARA_ERROR_LOG("%s\n", para_strerror(-ret)); + free(get_confdir()); return ret < 0? EXIT_FAILURE : EXIT_SUCCESS; }