+ return 0;
+ }
+ lsu_com_help(long_help, lpr, play_cmd_suite, NULL, &buf, &n);
+ btr_add_output(buf, n, pt->btrn);
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(help);
+
+static int com_info(__a_unused struct lls_parse_result *lpr)
+{
+ char *buf;
+ size_t sz;
+ static char dflt[] = "[no information available]";
+
+ sz = xasprintf(&buf, "playlist_pos: %u\npath: %s\n",
+ pt->current_file, get_playlist_file(pt->current_file));
+ btr_add_output(buf, sz, pt->btrn);
+ buf = pt->afhi_txt? pt->afhi_txt : dflt;
+ btr_add_output_dont_free(buf, strlen(buf), pt->btrn);
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(info);
+
+static void list_file(int num)
+{
+ char *buf;
+ size_t sz;
+
+ sz = xasprintf(&buf, "%s %4d %s\n", num == pt->current_file?
+ "*" : " ", num, get_playlist_file(num));
+ btr_add_output(buf, sz, pt->btrn);
+}
+
+static int com_tasks(__a_unused struct lls_parse_result *lpr)
+{
+ static char state;
+ char *buf;
+ size_t sz;
+
+ buf = get_task_list(&sched);
+ btr_add_output(buf, strlen(buf), pt->btrn);
+ state = get_playback_state();
+ sz = xasprintf(&buf, "state: %c\n", state);
+ btr_add_output(buf, sz, pt->btrn);
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(tasks);
+
+static int com_ls(__a_unused struct lls_parse_result *lpr)
+{
+ int i;
+ unsigned num_inputs = lls_num_inputs(play_lpr);
+
+ for (i = 0; i < num_inputs; i++)
+ list_file(i);
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(ls);
+
+static int com_play(struct lls_parse_result *lpr)
+{
+ int32_t x;
+ int ret;
+ char state, *errctx;
+
+ ret = lls(lls_check_arg_count(lpr, 0, 1, &errctx));
+ if (ret < 0) {
+ if (errctx)
+ PARA_ERROR_LOG("%s\n", errctx);
+ free(errctx);
+ return ret;
+ }
+ state = get_playback_state();
+ if (lls_num_inputs(lpr) == 0) {
+ if (state == 'P')
+ return 0;
+ pt->next_file = pt->current_file;
+ pt->rq = CRT_REPOS;
+ pt->playing = true;
+ return 0;
+ }
+ ret = para_atoi32(lls_input(0, lpr), &x);
+ if (ret < 0)
+ return ret;
+ if (x < 0 || x >= lls_num_inputs(play_lpr))
+ return -ERRNO_TO_PARA_ERROR(EINVAL);
+ kill_stream();
+ pt->next_file = x;
+ pt->rq = CRT_FILE_CHANGE;
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(play);
+
+static int com_pause(__a_unused struct lls_parse_result *lpr)
+{
+ char state;
+ long unsigned seconds, ss;
+
+ state = get_playback_state();
+ pt->playing = false;
+ if (state != 'P')
+ return 0;
+ seconds = get_play_time();
+ pt->playing = false;
+ ss = 0;
+ if (pt->seconds > 0)
+ ss = seconds * pt->num_chunks / pt->seconds + 1;
+ ss = PARA_MAX(ss, 0UL);
+ ss = PARA_MIN(ss, pt->num_chunks);
+ pt->start_chunk = ss;
+ kill_stream();
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(pause);
+
+static int com_prev(__a_unused struct lls_parse_result *lpr)
+{
+ int ret;
+
+ ret = previous_valid_file();
+ if (ret < 0)
+ return ret;
+ kill_stream();
+ pt->next_file = ret;
+ pt->rq = CRT_FILE_CHANGE;
+ pt->start_chunk = 0;
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(prev);
+
+static int com_next(__a_unused struct lls_parse_result *lpr)
+{
+ int ret;
+
+ ret = next_valid_file();
+ if (ret < 0)
+ return ret;
+ kill_stream();
+ pt->next_file = ret;
+ pt->rq = CRT_FILE_CHANGE;
+ pt->start_chunk = 0;
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(next);
+
+static int com_fg(__a_unused struct lls_parse_result *lpr)
+{
+ pt->background = false;
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(fg);
+
+static int com_bg(__a_unused struct lls_parse_result *lpr)
+{
+ pt->background = true;
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(bg);
+
+static int com_jmp(struct lls_parse_result *lpr)
+{
+ int32_t percent;
+ int ret;
+ char *errctx;
+
+ ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx));
+ if (ret < 0) {
+ if (errctx)
+ PARA_ERROR_LOG("%s\n", errctx);
+ free(errctx);
+ return ret;
+ }
+ ret = para_atoi32(lls_input(0, lpr), &percent);
+ if (ret < 0)
+ return ret;
+ if (percent < 0 || percent > 100)
+ return -ERRNO_TO_PARA_ERROR(EINVAL);
+ if (percent == 100)
+ return com_next(NULL);
+ if (pt->playing && !pt->fn.btrn)
+ return 0;
+ pt->start_chunk = percent * pt->num_chunks / 100;
+ if (!pt->playing)
+ return 0;
+ pt->rq = CRT_REPOS;
+ kill_stream();
+ return 0;
+}
+EXPORT_PLAY_CMD_HANDLER(jmp);
+
+static int com_ff(struct lls_parse_result *lpr)
+{
+ int32_t seconds;
+ char *errctx;
+ int ret;
+
+ ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx));
+ if (ret < 0) {
+ if (errctx)
+ PARA_ERROR_LOG("%s\n", errctx);
+ free(errctx);
+ return ret;