diff --git a/input/input.c b/input/input.c index 6b457bad7f..e422e9f1a2 100644 --- a/input/input.c +++ b/input/input.c @@ -622,6 +622,8 @@ struct input_ctx { struct cmd_queue key_cmd_queue; struct cmd_queue control_cmd_queue; + + int wakeup_pipe[2]; }; @@ -1104,6 +1106,13 @@ static int default_cmd_func(int fd, char *buf, int l) } } +static int read_wakeup(void *ctx, int fd) +{ + char buf[100]; + read(fd, buf, sizeof(buf)); + return MP_INPUT_NOTHING; +} + static char *find_bind_for_key(const struct cmd_bind *binds, int n, int *keys) { @@ -1126,7 +1135,7 @@ static char *find_bind_for_key(const struct cmd_bind *binds, int n, int *keys) } static struct cmd_bind_section *get_bind_section(struct input_ctx *ictx, - char *section) + char *section) { struct cmd_bind_section *bind_section = ictx->cmd_bind_sections; @@ -1731,8 +1740,25 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf) .ar_delay = input_conf->ar_delay, .ar_rate = input_conf->ar_rate, .default_bindings = input_conf->default_bindings, + .wakeup_pipe = {-1, -1}, }; +#ifndef __MINGW32__ + long ret = pipe(ictx->wakeup_pipe); + for (int i = 0; i < 2 && ret >= 0; i++) { + ret = fcntl(ictx->wakeup_pipe[i], F_GETFL); + if (ret < 0) + break; + ret = fcntl(ictx->wakeup_pipe[i], F_SETFL, ret | O_NONBLOCK); + } + if (ret < 0) + mp_msg(MSGT_INPUT, MSGL_ERR, + "Failed to initialize wakeup pipe: %s\n", strerror(errno)); + else + mp_input_add_key_fd(ictx, ictx->wakeup_pipe[0], true, read_wakeup, + NULL, NULL); +#endif + char *file; char *config_file = input_conf->config_file; file = config_file[0] != '/' ? get_path(config_file) : config_file; @@ -1830,17 +1856,17 @@ void mp_input_uninit(struct input_ctx *ictx) if (!ictx) return; - unsigned int i; - - for (i = 0; i < ictx->num_key_fd; i++) { + for (int i = 0; i < ictx->num_key_fd; i++) { if (ictx->key_fds[i].close_func) ictx->key_fds[i].close_func(ictx->key_fds[i].fd); } - - for (i = 0; i < ictx->num_cmd_fd; i++) { + for (int i = 0; i < ictx->num_cmd_fd; i++) { if (ictx->cmd_fds[i].close_func) ictx->cmd_fds[i].close_func(ictx->cmd_fds[i].fd); } + for (int i = 0; i < 2; i++) + if (ictx->wakeup_pipe[i] != -1) + close(ictx->wakeup_pipe[i]); talloc_free(ictx); } @@ -1890,6 +1916,12 @@ static int print_cmd_list(m_option_t *cfg) exit(0); } +void mp_input_wakeup(struct input_ctx *ictx) +{ + if (ictx->wakeup_pipe[1] >= 0) + write(ictx->wakeup_pipe[1], &(char){0}, 1); +} + /** * \param time time to wait for an interruption in milliseconds */ diff --git a/input/input.h b/input/input.h index 4cd006fa9a..c5f6940990 100644 --- a/input/input.h +++ b/input/input.h @@ -272,6 +272,9 @@ void mp_input_uninit(struct input_ctx *ictx); struct m_config; void mp_input_register_options(struct m_config *cfg); +// Wake up sleeping input loop from another thread. +void mp_input_wakeup(struct input_ctx *ictx); + // Interruptible usleep: (used by libmpdemux) int mp_input_check_interrupt(struct input_ctx *ictx, int time); diff --git a/libao2/ao_pulse.c b/libao2/ao_pulse.c index 659a2bc907..ddaf35716c 100644 --- a/libao2/ao_pulse.c +++ b/libao2/ao_pulse.c @@ -30,6 +30,7 @@ #include "libaf/af_format.h" #include "mp_msg.h" #include "audio_out.h" +#include "input/input.h" #define PULSE_CLIENT_NAME "mplayer2" @@ -84,6 +85,7 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { struct ao *ao = userdata; struct priv *priv = ao->priv; + mp_input_wakeup(ao->input_ctx); pa_threaded_mainloop_signal(priv->mainloop, 0); } @@ -263,8 +265,14 @@ static int init(struct ao *ao, char *params) pa_stream_set_write_callback(priv->stream, stream_request_cb, ao); pa_stream_set_latency_update_callback(priv->stream, stream_latency_update_cb, ao); - - if (pa_stream_connect_playback(priv->stream, sink, NULL, + pa_buffer_attr bufattr = { + .maxlength = -1, + .tlength = pa_usec_to_bytes(1000000, &ss), + .prebuf = -1, + .minreq = -1, + .fragsize = -1, + }; + if (pa_stream_connect_playback(priv->stream, sink, &bufattr, PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) diff --git a/libao2/audio_out.c b/libao2/audio_out.c index a91a0d6d72..6130e2ed33 100644 --- a/libao2/audio_out.c +++ b/libao2/audio_out.c @@ -136,10 +136,11 @@ void list_audio_out(void) mp_msg(MSGT_GLOBAL, MSGL_INFO,"\n"); } -struct ao *ao_create(void) +struct ao *ao_create(struct MPOpts *opts, struct input_ctx *input) { struct ao *r = talloc(NULL, struct ao); - *r = (struct ao){.outburst = OUTBURST, .buffersize = -1}; + *r = (struct ao){.outburst = OUTBURST, .buffersize = -1, + .opts = opts, .input_ctx = input }; return r; } diff --git a/libao2/audio_out.h b/libao2/audio_out.h index cbd913656b..1c472565a0 100644 --- a/libao2/audio_out.h +++ b/libao2/audio_out.h @@ -81,6 +81,7 @@ struct ao { const struct ao_driver *driver; void *priv; struct MPOpts *opts; + struct input_ctx *input_ctx; }; extern char *ao_subdevice; @@ -109,7 +110,7 @@ typedef struct ao_control_vol { float right; } ao_control_vol_t; -struct ao *ao_create(void); +struct ao *ao_create(struct MPOpts *opts, struct input_ctx *input); void ao_init(struct ao *ao, char **ao_list); void ao_uninit(struct ao *ao, bool cut_audio); int ao_play(struct ao *ao, void *data, int len, int flags); diff --git a/mplayer.c b/mplayer.c index 4f7027ec79..eb278353e3 100644 --- a/mplayer.c +++ b/mplayer.c @@ -1775,8 +1775,7 @@ void reinit_audio_chain(struct MPContext *mpctx) current_module = "af_preinit"; if (!(mpctx->initialized_flags & INITIALIZED_AO)) { mpctx->initialized_flags |= INITIALIZED_AO; - mpctx->ao = ao_create(); - mpctx->ao->opts = opts; + mpctx->ao = ao_create(opts, mpctx->input); mpctx->ao->samplerate = force_srate; mpctx->ao->format = opts->audio_output_format; }