summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-09-07 20:44:54 +0200
committerwm4 <wm4@nowhere>2014-09-07 20:44:54 +0200
commitf5af5962378bd40a409716434a6a4d312e50c755 (patch)
tree0d507b7254fbd159a6ca0c29f4c0261c4a4becb4
parent5546af421f853170ad3142008503bb865a81adef (diff)
downloadmpv-f5af5962378bd40a409716434a6a4d312e50c755.tar.bz2
mpv-f5af5962378bd40a409716434a6a4d312e50c755.tar.xz
player: some more input refactoring
Continues commit 348dfd93. Replace other places where input was manually fetched with common code. demux_was_interrupted() was a weird function; I'm not entirely sure about its original purpose, but now we can just replace it with simpler code as well. One difference is that we always look at the command queue, rather than just when cache initialization failed. Also, instead of discarding all but quit/playlist commands (aka abort command), run all commands. This could possibly lead to unwanted side-effects, like just ignoring commands that have no effect (consider pressing 'f' for fullscreen right on start: since the window is not created yet, it would get discarded). But playlist navigation still works as intended, and some if not all these problems already existed before that in some forms, so it should be ok.
-rw-r--r--input/input.c29
-rw-r--r--input/input.h12
-rw-r--r--player/loadfile.c34
-rw-r--r--player/main.c2
-rw-r--r--player/misc.c8
-rw-r--r--player/playloop.c30
6 files changed, 42 insertions, 73 deletions
diff --git a/input/input.c b/input/input.c
index d2a57c726e..328877eeb4 100644
--- a/input/input.c
+++ b/input/input.c
@@ -192,6 +192,7 @@ int async_quit_request;
static int parse_config(struct input_ctx *ictx, bool builtin, bstr data,
const char *location, const char *restrict_section);
static void close_input_sources(struct input_ctx *ictx);
+static bool test_abort(struct input_ctx *ictx);
#define OPT_BASE_STRUCT struct input_opts
struct input_opts {
@@ -1158,21 +1159,27 @@ static mp_cmd_t *check_autorepeat(struct input_ctx *ictx)
return NULL;
}
-/**
- * \param peek_only when set, the returned command stays in the queue.
- * Do not free the returned cmd whe you set this!
- */
-mp_cmd_t *mp_input_get_cmd(struct input_ctx *ictx, int time, int peek_only)
+void mp_input_wait(struct input_ctx *ictx, double seconds)
+{
+ if (seconds <= 0)
+ return;
+ input_lock(ictx);
+ if (ictx->cmd_queue.first)
+ seconds = 0;
+ MP_STATS(ictx, "start sleep");
+ read_events(ictx, MPMIN(seconds * 1000, INT_MAX));
+ MP_STATS(ictx, "end sleep");
+ input_unlock(ictx);
+}
+
+mp_cmd_t *mp_input_read_cmd(struct input_ctx *ictx)
{
input_lock(ictx);
- if (async_quit_request) {
+ read_events(ictx, 0);
+ if (async_quit_request && !test_abort(ictx)) {
struct mp_cmd *cmd = mp_input_parse_cmd(ictx, bstr0("quit"), "");
queue_add_head(&ictx->cmd_queue, cmd);
}
-
- if (ictx->cmd_queue.first)
- time = 0;
- read_events(ictx, time);
struct cmd_queue *queue = &ictx->cmd_queue;
if (!queue->first) {
struct mp_cmd *repeated = check_autorepeat(ictx);
@@ -1186,7 +1193,7 @@ mp_cmd_t *mp_input_get_cmd(struct input_ctx *ictx, int time, int peek_only)
}
}
struct mp_cmd *ret = queue_peek(queue);
- if (ret && !peek_only) {
+ if (ret) {
queue_remove(queue, ret);
if (ret->mouse_move) {
ictx->mouse_x = ret->mouse_x;
diff --git a/input/input.h b/input/input.h
index 431519a47c..6ab1392111 100644
--- a/input/input.h
+++ b/input/input.h
@@ -179,12 +179,8 @@ void mp_input_rm_key_fd(struct input_ctx *ictx, int fd);
// Add a command to the command queue.
int mp_input_queue_cmd(struct input_ctx *ictx, struct mp_cmd *cmd);
-/* Return next available command, or sleep up to "time" ms if none is
- * available. If "peek_only" is true return a reference to the command
- * but leave it queued.
- */
-struct mp_cmd *mp_input_get_cmd(struct input_ctx *ictx, int time,
- int peek_only);
+// Return next queued command, or NULL.
+struct mp_cmd *mp_input_read_cmd(struct input_ctx *ictx);
// Parse text and return corresponding struct mp_cmd.
// The location parameter is for error messages.
@@ -240,6 +236,10 @@ struct input_ctx *mp_input_init(struct mpv_global *global);
void mp_input_uninit(struct input_ctx *ictx);
+// Sleep for the given amount of seconds, until mp_input_wakeup() is called,
+// or new input arrives. seconds<=0 returns immediately.
+void mp_input_wait(struct input_ctx *ictx, double seconds);
+
// Wake up sleeping input loop from another thread.
void mp_input_wakeup(struct input_ctx *ictx);
diff --git a/player/loadfile.c b/player/loadfile.c
index 33c71462cc..9c6aabdd4e 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -985,26 +985,6 @@ static void load_chapters(struct MPContext *mpctx)
}
}
-/* When demux performs a blocking operation (network connection or
- * cache filling) if the operation fails we use this function to check
- * if it was interrupted by the user.
- * The function returns whether it was interrupted. */
-static bool demux_was_interrupted(struct MPContext *mpctx)
-{
- for (;;) {
- if (mpctx->stop_play != KEEP_PLAYING
- && mpctx->stop_play != AT_END_OF_FILE)
- return true;
- mp_cmd_t *cmd = mp_input_get_cmd(mpctx->input, 0, 0);
- if (!cmd)
- break;
- if (mp_input_is_abort_cmd(cmd))
- run_command(mpctx, cmd);
- mp_cmd_free(cmd);
- }
- return false;
-}
-
static void load_per_file_options(m_config_t *conf,
struct playlist_param *params,
int params_count)
@@ -1023,8 +1003,6 @@ static void play_current_file(struct MPContext *mpctx)
void *tmp = talloc_new(NULL);
double playback_start = -1e100;
- mpctx->initialized_flags |= INITIALIZED_PLAYBACK;
-
mp_notify(mpctx, MPV_EVENT_START_FILE, NULL);
mpctx->stop_play = 0;
@@ -1112,7 +1090,7 @@ static void play_current_file(struct MPContext *mpctx)
stream_flags |= mpctx->playlist->current->stream_flags;
mpctx->stream = stream_create(stream_filename, stream_flags, mpctx->global);
if (!mpctx->stream) { // error...
- demux_was_interrupted(mpctx);
+ mp_process_input(mpctx);
goto terminate_playback;
}
mpctx->initialized_flags |= INITIALIZED_STREAM;
@@ -1125,10 +1103,11 @@ static void play_current_file(struct MPContext *mpctx)
// Must be called before enabling cache.
mp_nav_init(mpctx);
- int res = stream_enable_cache(&mpctx->stream, &opts->stream_cache);
- if (res == 0)
- if (demux_was_interrupted(mpctx))
- goto terminate_playback;
+ stream_enable_cache(&mpctx->stream, &opts->stream_cache);
+
+ mp_process_input(mpctx);
+ if (mpctx->stop_play)
+ goto terminate_playback;
stream_set_capture_file(mpctx->stream, opts->stream_capture);
@@ -1297,6 +1276,7 @@ goto_reopen_demuxer: ;
if (mpctx->opts->pause)
pause_player(mpctx);
+ mpctx->initialized_flags |= INITIALIZED_PLAYBACK;
mp_notify(mpctx, MPV_EVENT_FILE_LOADED, NULL);
playback_start = mp_time_sec();
diff --git a/player/main.c b/player/main.c
index 97ccb0e639..6f9a0fcca8 100644
--- a/player/main.c
+++ b/player/main.c
@@ -111,7 +111,7 @@ static void shutdown_clients(struct MPContext *mpctx)
while (mpctx->clients && mp_clients_num(mpctx)) {
mp_client_broadcast_event(mpctx, MPV_EVENT_SHUTDOWN, NULL);
mp_dispatch_queue_process(mpctx->dispatch, 0);
- mp_input_get_cmd(mpctx->input, 100, 1);
+ mp_wait_events(mpctx, 10000);
}
mp_clients_destroy(mpctx);
}
diff --git a/player/misc.c b/player/misc.c
index bc3a1980c9..51f3e0f863 100644
--- a/player/misc.c
+++ b/player/misc.c
@@ -188,13 +188,7 @@ void stream_dump(struct MPContext *mpctx)
(long long int)pos, (long long int)size);
}
stream_fill_buffer(stream);
- for (;;) {
- mp_cmd_t *cmd = mp_input_get_cmd(mpctx->input, 0, false);
- if (!cmd)
- break;
- run_command(mpctx, cmd);
- talloc_free(cmd);
- }
+ mp_process_input(mpctx);
}
}
diff --git a/player/playloop.c b/player/playloop.c
index 06c0f02bf6..d476137c12 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -56,27 +56,22 @@
// mp_wait_events() was called. (But see mp_process_input().)
void mp_wait_events(struct MPContext *mpctx, double sleeptime)
{
- if (sleeptime > 0) {
- MP_STATS(mpctx, "start sleep");
- mp_input_get_cmd(mpctx->input, sleeptime * 1000, true);
- MP_STATS(mpctx, "end sleep");
- }
+ mp_input_wait(mpctx->input, sleeptime);
}
// Process any queued input, whether it's user input, or requests from client
// API threads. This also resets the "wakeup" flag used with mp_wait_events().
void mp_process_input(struct MPContext *mpctx)
{
- mp_cmd_t *cmd;
- while ((cmd = mp_input_get_cmd(mpctx->input, 0, 1)) != NULL) {
- mp_dispatch_queue_process(mpctx->dispatch, 0);
- cmd = mp_input_get_cmd(mpctx->input, 0, 0);
+ mp_dispatch_queue_process(mpctx->dispatch, 0);
+ for (;;) {
+ mp_cmd_t *cmd = mp_input_read_cmd(mpctx->input);
+ if (!cmd)
+ break;
run_command(mpctx, cmd);
mp_cmd_free(cmd);
- if (mpctx->stop_play)
- break;
+ mp_dispatch_queue_process(mpctx->dispatch, 0);
}
- mp_dispatch_queue_process(mpctx->dispatch, 0);
}
void pause_player(struct MPContext *mpctx)
@@ -976,8 +971,6 @@ void idle_loop(struct MPContext *mpctx)
while (mpctx->opts->player_idle_mode && !mpctx->playlist->current
&& mpctx->stop_play != PT_QUIT)
{
- mpctx->video_status = STATUS_EOF;
- mpctx->audio_status = STATUS_EOF;
if (need_reinit) {
mp_notify(mpctx, MPV_EVENT_IDLE, NULL);
handle_force_window(mpctx, true);
@@ -988,16 +981,11 @@ void idle_loop(struct MPContext *mpctx)
if (!mpctx->opts->force_vo)
uninit |= INITIALIZED_VO;
uninit_player(mpctx, uninit);
- handle_force_window(mpctx, false);
update_osd_msg(mpctx);
handle_osd_redraw(mpctx);
- mp_cmd_t *cmd = mp_input_get_cmd(mpctx->input, mpctx->sleeptime * 1000,
- false);
+ mp_process_input(mpctx);
+ mp_wait_events(mpctx, mpctx->sleeptime);
mpctx->sleeptime = 100.0;
- if (cmd)
- run_command(mpctx, cmd);
- mp_cmd_free(cmd);
- mp_dispatch_queue_process(mpctx->dispatch, 0);
if (mpctx->opts->use_terminal)
getch2_poll();
}