diff options
-rw-r--r-- | DOCS/man/en/options.rst | 7 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | audio/out/ao_wasapi0.c | 107 | ||||
-rwxr-xr-x | configure | 38 | ||||
-rw-r--r-- | core/input/input.c | 293 | ||||
-rw-r--r-- | core/input/input.h | 3 | ||||
-rw-r--r-- | core/m_struct.h | 10 | ||||
-rw-r--r-- | core/mp_ring.c | 2 | ||||
-rw-r--r-- | core/mp_ring.h | 13 | ||||
-rw-r--r-- | core/mplayer.c | 2 | ||||
-rw-r--r-- | core/options.c | 3 | ||||
-rw-r--r-- | core/options.h | 1 | ||||
-rw-r--r-- | core/timeline/tl_matroska.c | 4 | ||||
-rw-r--r-- | core/version.c | 6 | ||||
-rw-r--r-- | osdep/getch2-win.c | 234 | ||||
-rw-r--r-- | osdep/mpv.exe.manifest | 18 | ||||
-rw-r--r-- | stream/cache.c | 2 | ||||
-rw-r--r-- | stream/stream.c | 38 | ||||
-rw-r--r-- | stream/stream.h | 4 | ||||
-rw-r--r-- | stream/stream_vcd.c | 2 | ||||
-rw-r--r-- | video/filter/vf.c | 2 | ||||
-rw-r--r-- | video/out/cocoa_common.m | 8 |
22 files changed, 396 insertions, 404 deletions
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index a6e5fee7ed..58fc365db1 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -309,7 +309,7 @@ Set the size of the cache in kilobytes, disable it with ``no``, or automatically enable it if needed with ``auto`` (default: ``auto``). With ``auto``, the cache will usually be enabled for network streams, - using a default size. + using the size set by ``--cache-default``. May be useful when playing files from slow media, but can also have negative effects, especially with file formats that require a lot of @@ -321,6 +321,11 @@ seeking back. Likewise, when starting a file the cache will be at 100%, because no space is reserved for seeking back yet. +``--cache-default=<kBytes|no>`` + Set the size of the cache in kilobytes (default: 320 KB). Using ``no`` + will not automatically enable the cache e.h. when playing from a network + stream. Note that using ``--cache`` will always override this option. + ``--cache-pause=<no|percentage>`` If the cache percentage goes below the specified value, pause and wait until the percentage set by ``--cache-min`` is reached, then resume @@ -116,6 +116,8 @@ ifeq ($(HAVE_AVUTIL_REFCOUNTING),no) SOURCES-yes += video/decode/lavc_dr1.c endif +SOURCES-$(DLOPEN) += video/filter/vf_dlopen.c + SOURCES = talloc.c \ audio/audio.c \ audio/chmap.c \ @@ -235,7 +237,6 @@ SOURCES = talloc.c \ video/filter/vf_crop.c \ video/filter/vf_delogo.c \ video/filter/vf_divtc.c \ - video/filter/vf_dlopen.c \ video/filter/vf_down3dright.c \ video/filter/vf_dsize.c \ video/filter/vf_eq.c \ diff --git a/audio/out/ao_wasapi0.c b/audio/out/ao_wasapi0.c index 8d0fe27801..a45ca829e5 100644 --- a/audio/out/ao_wasapi0.c +++ b/audio/out/ao_wasapi0.c @@ -30,6 +30,7 @@ #include "core/subopt-helper.h" #include "audio/format.h" #include "core/mp_msg.h" +#include "core/mp_ring.h" #include "ao.h" #define RING_BUFFER_COUNT 64 @@ -75,17 +76,13 @@ typedef struct wasapi0_state { CRITICAL_SECTION print_lock; /* Buffers */ - CRITICAL_SECTION buffer_lock; + struct mp_ring *ringbuff; size_t buffer_block_size; /* Size of each block in bytes */ - LONG read_block_ptr, write_block_ptr; /*Which block are we in?*/ - LONG write_ahead_count; /* how many blocks writer is ahead of reader? should be less than RING_BUFFER_COUNT*/ - uintptr_t write_offset; /*offset while writing partial blocks, used only in main thread */ REFERENCE_TIME minRequestedDuration; /* minimum wasapi buffer block size, in 100-nanosecond units */ REFERENCE_TIME defaultRequestedDuration; /* default wasapi default block size, in 100-nanosecond units */ UINT32 bufferFrameCount; /* wasapi buffer block size, number of frames, frame size at format.nBlockAlign */ - void *ring_buffer[RING_BUFFER_COUNT]; /* each bufferFrameCount sized, owned by main thread */ /* WASAPI handles, owned by other thread */ IMMDeviceEnumerator *pEnumerator; @@ -317,7 +314,6 @@ static int fix_format(struct wasapi0_state *state) /* cargo cult code to negotiate buffer block size, affected by hardware/drivers combinations, gradually grow it to 10s, by 0.5s, consider failure if it still doesn't work */ - EnterCriticalSection(&state->buffer_lock); hr = IAudioClient_GetDevicePeriod(state->pAudioClient, &state->defaultRequestedDuration, &state->minRequestedDuration); @@ -365,7 +361,6 @@ reinit: EXIT_ON_ERROR(hr) state->buffer_block_size = state->format.Format.nBlockAlign * state->bufferFrameCount; - LeaveCriticalSection(&state->buffer_lock); state->hTask = state->VistaBlob.pAvSetMmThreadCharacteristicsW(L"Pro Audio", &state->taskIndex); EnterCriticalSection(&state->print_lock); @@ -380,7 +375,6 @@ exit_label: "ao-wasapi: fix_format fails with %s, failed to determine buffer block size!\n", explain_err(hr)); LeaveCriticalSection(&state->print_lock); - LeaveCriticalSection(&state->buffer_lock); SetEvent(state->fatal_error); return 1; } @@ -440,22 +434,23 @@ static void thread_reset(wasapi0_state *state) IAudioClient_Reset(state->pAudioClient); } -static void thread_feed(wasapi0_state *state) +/* force_feed - feed in even if available data is smaller than required buffer, to clear the buffer */ +static void thread_feed(wasapi0_state *state,int force_feed) { BYTE *pData; + int buffer_size; HRESULT hr = IAudioRenderClient_GetBuffer(state->pRenderClient, state->bufferFrameCount, &pData); EXIT_ON_ERROR(hr) - EnterCriticalSection(&state->buffer_lock); - if (state->write_ahead_count > 0) { /* OK to copy! */ - memcpy(pData, state->ring_buffer[state->read_block_ptr], - state->buffer_block_size); - state->read_block_ptr++; - state->read_block_ptr = state->read_block_ptr % RING_BUFFER_COUNT; - state->write_ahead_count--; - LeaveCriticalSection(&state->buffer_lock); + buffer_size = mp_ring_buffered(state->ringbuff); + if( buffer_size > state->buffer_block_size) { /* OK to copy! */ + mp_ring_read(state->ringbuff, (unsigned char *)pData, + state->buffer_block_size); + } else if(force_feed) { + /* should be smaller than buffer block size by now */ + memset(pData,0,state->buffer_block_size); + mp_ring_read(state->ringbuff, (unsigned char *)pData, buffer_size); } else { - LeaveCriticalSection(&state->buffer_lock); /* buffer underrun?! abort */ hr = IAudioRenderClient_ReleaseBuffer(state->pRenderClient, state->bufferFrameCount, @@ -475,7 +470,7 @@ exit_label: static void thread_play(wasapi0_state *state) { - thread_feed(state); + thread_feed(state, 0); IAudioClient_Start(state->pAudioClient); return; } @@ -499,11 +494,10 @@ static void thread_uninit(wasapi0_state *state) if (!state->immed) { /* feed until empty */ while (1) { - EnterCriticalSection(&state->buffer_lock); - LONG ahead = state->write_ahead_count; - LeaveCriticalSection(&state->buffer_lock); - if (WaitForSingleObject(state->hFeed, 2000) == WAIT_OBJECT_0 && ahead) { - thread_feed(state); + if (WaitForSingleObject(state->hFeed,2000) == WAIT_OBJECT_0 && + mp_ring_buffered(state->ringbuff)) + { + thread_feed(state, 1); } else break; } @@ -568,7 +562,7 @@ static unsigned int __stdcall ThreadLoop(void *lpParameter) break; case (WAIT_OBJECT_0 + 6): /* feed */ feedwatch = 1; - thread_feed(state); + thread_feed(state, 0); break; case WAIT_TIMEOUT: /* Did our feed die? */ if (feedwatch) @@ -608,48 +602,22 @@ static void closehandles(struct ao *ao) static int get_space(struct ao *ao) { - int ret = 0; if (!ao || !ao->priv) return -1; struct wasapi0_state *state = (struct wasapi0_state *)ao->priv; - EnterCriticalSection(&state->buffer_lock); - LONG ahead = state->write_ahead_count; - size_t block_size = state->buffer_block_size; - LeaveCriticalSection(&state->buffer_lock); - ret = (RING_BUFFER_COUNT - ahead) * block_size; /* rough */ - return ret - (block_size - state->write_offset); /* take offset into account */ + return mp_ring_available(state->ringbuff); } static void reset_buffers(struct wasapi0_state *state) { - EnterCriticalSection(&state->buffer_lock); - state->read_block_ptr = state->write_block_ptr = 0; - state->write_ahead_count = 0; - state->write_offset = 0; - LeaveCriticalSection(&state->buffer_lock); -} - -static void free_buffers(struct wasapi0_state *state) -{ - int iter; - for (iter = 0; iter < RING_BUFFER_COUNT; iter++) { - free(state->ring_buffer[iter]); - state->ring_buffer[iter] = NULL; - } + mp_ring_reset(state->ringbuff); } static int setup_buffers(struct wasapi0_state *state) { - int iter; - reset_buffers(state); - for (iter = 0; iter < RING_BUFFER_COUNT; iter++) { - state->ring_buffer[iter] = malloc(state->buffer_block_size); - if (!state->ring_buffer[iter]) { - free_buffers(state); - return 1; /* failed */ - } - } - return 0; + state->ringbuff = + mp_ring_new(state, RING_BUFFER_COUNT * state->buffer_block_size); + return !state->ringbuff; } static void uninit(struct ao *ao, bool immed) @@ -663,9 +631,7 @@ static void uninit(struct ao *ao, bool immed) SetEvent(state->fatal_error); if (state->VistaBlob.hAvrt) FreeLibrary(state->VistaBlob.hAvrt); - free_buffers(state); closehandles(ao); - DeleteCriticalSection(&state->buffer_lock); DeleteCriticalSection(&state->print_lock); talloc_free(state); ao->priv = NULL; @@ -694,7 +660,6 @@ static int init(struct ao *ao, char *params) state->hUninit = CreateEventW(NULL, FALSE, FALSE, NULL); state->fatal_error = CreateEventW(NULL, TRUE, FALSE, NULL); state->hFeed = CreateEvent(NULL, FALSE, FALSE, NULL); /* for wasapi event mode */ - InitializeCriticalSection(&state->buffer_lock); InitializeCriticalSection(&state->print_lock); if (!state->init_done || !state->fatal_error || !state->hPlay || !state->hPause || !state->hFeed || !state->hReset || !state->hGetvol || @@ -772,7 +737,6 @@ static void reset(struct ao *ao) static int play(struct ao *ao, void *data, int len, int flags) { int ret = 0; - unsigned char *dat = data; if (!ao || !ao->priv) return ret; struct wasapi0_state *state = (struct wasapi0_state *)ao->priv; @@ -781,28 +745,7 @@ static int play(struct ao *ao, void *data, int len, int flags) return ret; } - /* round to nearest block size? */ - EnterCriticalSection(&state->buffer_lock); - /* make sure write ahead does not bust buffer count */ - while ((RING_BUFFER_COUNT - 1) > state->write_ahead_count) { - /* data left is larger than block size, do block by block copy */ - if ((len - ret) > state->buffer_block_size) { - memcpy(state->ring_buffer[state->write_block_ptr], &dat[ret], - state->buffer_block_size); - } else if (flags & AOPLAY_FINAL_CHUNK) { - /* zero out and fill with whatever that is left, but only if it is final block */ - memset(state->ring_buffer[state->write_block_ptr], 0, - state->buffer_block_size); - memcpy(state->ring_buffer[state->write_block_ptr], &dat[ret], - (len - ret)); - } else - break; /* otherwise leave buffers outside of block alignment and let player figure it out */ - state->write_block_ptr++; - state->write_block_ptr %= RING_BUFFER_COUNT; - state->write_ahead_count++; - ret += state->buffer_block_size; - } - LeaveCriticalSection(&state->buffer_lock); + ret = mp_ring_write(state->ringbuff, data, len); if (!state->is_playing) { /* start playing */ @@ -379,6 +379,7 @@ Miscellaneous options: --enable-static build a statically linked binary --with-install=PATH path to a custom install program --disable-manpage do not build and install manpage [auto] + --disable-build-date do not include binary compile time Advanced options: --enable-shm enable shm [autodetect] @@ -487,6 +488,7 @@ _priority=no def_dos_paths="#define HAVE_DOS_PATHS 0" def_priority="#undef CONFIG_PRIORITY" _build_man=auto +_build_date=yes for ac_option do case "$ac_option" in --help|-help|-h) @@ -708,6 +710,8 @@ for ac_option do --enable-manpage) _build_man=yes ;; --disable-manpage) _build_man=no ;; + --enable-build-date) _build_date=yes ;; + --disable-build-date) _build_date=no ;; *) echo "Unknown parameter: $ac_option" >&2 exit 1 @@ -861,7 +865,9 @@ if darwin; then _timer=timer-darwin.c fi +_win32=no if win32 ; then + _win32=yes _exesuf=".exe" extra_cflags="$extra_cflags -fno-common" # -lwinmm is always needed for osdep/timer-win2.c @@ -900,6 +906,16 @@ else fi echores "$_build_man" +echocheck "whether to print binary build date" +if test "$_build_date" = yes ; then + _build_yes=yes +else + _build_date=no + extra_cflags="$extra_cflags -DNO_BUILD_TIMESTAMPS" +fi +echores "$_build_date" + + TMPC="$mplayer_tmpdir/tmp.c" TMPCPP="$mplayer_tmpdir/tmp.cpp" @@ -2356,7 +2372,7 @@ if test "$_vcd" = auto; then if linux || freebsd || netbsd || openbsd || dragonfly || darwin ; then _vcd=yes elif mingw32; then - header_check ntddcdrm.h && _vcd=yes + header_check_broken windows.h ntddcdrm.h && _vcd=yes fi fi if test "$_vcd" = yes; then @@ -2493,7 +2509,9 @@ echores "$_mpg123" echocheck "LADSPA plugin support" if test "$_ladspa" = auto ; then _ladspa=no - statement_check ladspa.h 'LADSPA_Descriptor ld = {0}' && _ladspa=yes + if test "$_dl" = yes ; then + statement_check ladspa.h 'LADSPA_Descriptor ld = {0}' && _ladspa=yes + fi fi if test "$_ladspa" = yes; then def_ladspa="#define CONFIG_LADSPA 1" @@ -2824,6 +2842,18 @@ fi echores "$_encoding" +# needs dlopen on unix, uses winapi on windows +_dlopen="$_dl" +if win32 ; then + _dlopen=yes +fi + +if test "$_dlopen" = yes ; then + def_dlopen='#define CONFIG_DLOPEN 1' +else + def_dlopen='#undef CONFIG_DLOPEN' +fi + ############################################################################# echocheck "compiler support for noexecstack" @@ -2947,6 +2977,8 @@ COCOA = $_cocoa COREAUDIO = $_coreaudio COREVIDEO = $_corevideo DIRECT3D = $_direct3d +DL = $_dl +DLOPEN = $_dlopen SDL = $_sdl SDL2 = $_sdl2 DSOUND = $_dsound @@ -2999,6 +3031,7 @@ TV = $_tv TV_V4L2 = $_tv_v4l2 VCD = $_vcd VDPAU = $_vdpau +WIN32 = $_win32 X11 = $_x11 WAYLAND = $_wayland XV = $_xv @@ -3106,6 +3139,7 @@ $def_libavfilter $def_vf_lavfi $def_af_lavfi +$def_dlopen /* Audio output drivers */ $def_alsa diff --git a/core/input/input.c b/core/input/input.c index e736c6486d..7ae76b9e04 100644 --- a/core/input/input.c +++ b/core/input/input.c @@ -462,27 +462,19 @@ struct key_name modifier_names[] = { { 0 } }; -#ifndef MP_MAX_KEY_FD -#define MP_MAX_KEY_FD 10 -#endif - -#ifndef MP_MAX_CMD_FD -#define MP_MAX_CMD_FD 10 -#endif +#define MP_MAX_FDS 10 struct input_fd { int fd; - union { - int (*key)(void *ctx, int fd); - int (*cmd)(int fd, char *dest, int size); - } read_func; + int (*read_key)(void *ctx, int fd); + int (*read_cmd)(int fd, char *dest, int size); int (*close_func)(int fd); void *ctx; unsigned eof : 1; unsigned drop : 1; unsigned dead : 1; unsigned got_cmd : 1; - unsigned no_select : 1; + unsigned select : 1; // These fields are for the cmd fds. char *buffer; int pos, size; @@ -553,11 +545,8 @@ struct input_ctx { unsigned int mouse_event_counter; - struct input_fd key_fds[MP_MAX_KEY_FD]; - unsigned int num_key_fd; - - struct input_fd cmd_fds[MP_MAX_CMD_FD]; - unsigned int num_cmd_fd; + struct input_fd fds[MP_MAX_FDS]; + unsigned int num_fds; struct cmd_queue key_cmd_queue; struct cmd_queue control_cmd_queue; @@ -700,98 +689,89 @@ static void queue_add(struct cmd_queue *queue, struct mp_cmd *cmd, } } -int mp_input_add_cmd_fd(struct input_ctx *ictx, int fd, int select, +static struct input_fd *mp_input_add_fd(struct input_ctx *ictx) +{ + if (ictx->num_fds == MP_MAX_FDS) { + mp_tmsg(MSGT_INPUT, MSGL_ERR, "Too many file descriptors.\n"); + return NULL; + } + + struct input_fd *fd = &ictx->fds[ictx->num_fds]; + *fd = (struct input_fd){ + .fd = -1, + }; + ictx->num_fds++; + + return fd; +} + +int mp_input_add_cmd_fd(struct input_ctx *ictx, int unix_fd, int select, int read_func(int fd, char *dest, int size), int close_func(int fd)) { - if (ictx->num_cmd_fd == MP_MAX_CMD_FD) { - mp_tmsg(MSGT_INPUT, MSGL_ERR, "Too many command file descriptors, " - "cannot register file descriptor %d.\n", fd); - return 0; - } - if (select && fd < 0) { + if (select && unix_fd < 0) { mp_msg(MSGT_INPUT, MSGL_ERR, - "Invalid fd %d in mp_input_add_cmd_fd", fd); + "Invalid fd %d in mp_input_add_cmd_fd", unix_fd); return 0; } - ictx->cmd_fds[ictx->num_cmd_fd] = (struct input_fd){ - .fd = fd, - .read_func.cmd = read_func ? read_func : default_cmd_func, - .close_func = close_func, - .no_select = !select - }; - ictx->num_cmd_fd++; - + struct input_fd *fd = mp_input_add_fd(ictx); + if (!fd) + return 0; + fd->fd = unix_fd; + fd->select = select; + fd->read_cmd = read_func ? read_func : default_cmd_func; + fd->close_func = close_func; return 1; } -void mp_input_rm_cmd_fd(struct input_ctx *ictx, int fd) +int mp_input_add_key_fd(struct input_ctx *ictx, int unix_fd, int select, + int read_func(void *ctx, int fd), + int close_func(int fd), void *ctx) { - struct input_fd *cmd_fds = ictx->cmd_fds; - unsigned int i; - - for (i = 0; i < ictx->num_cmd_fd; i++) { - if (cmd_fds[i].fd == fd) - break; + if (select && unix_fd < 0) { + mp_msg(MSGT_INPUT, MSGL_ERR, + "Invalid fd %d in mp_input_add_key_fd", unix_fd); + return 0; } - if (i == ictx->num_cmd_fd) - return; - if (cmd_fds[i].close_func) - cmd_fds[i].close_func(cmd_fds[i].fd); - talloc_free(cmd_fds[i].buffer); + assert(read_func); - if (i + 1 < ictx->num_cmd_fd) - memmove(&cmd_fds[i], &cmd_fds[i + 1], - (ictx->num_cmd_fd - i - 1) * sizeof(struct input_fd)); - ictx->num_cmd_fd--; + struct input_fd *fd = mp_input_add_fd(ictx); + if (!fd) + return 0; + fd->fd = unix_fd; + fd->select = select; + fd->read_key = read_func; + fd->close_func = close_func; + fd->ctx = ctx; + return 1; } -void mp_input_rm_key_fd(struct input_ctx *ictx, int fd) + +static void mp_input_rm_fd(struct input_ctx *ictx, int fd) { - struct input_fd *key_fds = ictx->key_fds; + struct input_fd *fds = ictx->fds; unsigned int i; - for (i = 0; i < ictx->num_key_fd; i++) { - if (key_fds[i].fd == fd) + for (i = 0; i < ictx->num_fds; i++) { + if (fds[i].fd == fd) break; } - if (i == ictx->num_key_fd) + if (i == ictx->num_fds) return; - if (key_fds[i].close_func) - key_fds[i].close_func(key_fds[i].fd); + if (fds[i].close_func) + fds[i].close_func(fds[i].fd); + talloc_free(fds[i].buffer); - if (i + 1 < ictx->num_key_fd) - memmove(&key_fds[i], &key_fds[i + 1], - (ictx->num_key_fd - i - 1) * sizeof(struct input_fd)); - ictx->num_key_fd--; + if (i + 1 < ictx->num_fds) + memmove(&fds[i], &fds[i + 1], + (ictx->num_fds - i - 1) * sizeof(struct input_fd)); + ictx->num_fds--; } -int mp_input_add_key_fd(struct input_ctx *ictx, int fd, int select, - int read_func(void *ctx, int fd), - int close_func(int fd), void *ctx) +void mp_input_rm_key_fd(struct input_ctx *ictx, int fd) { - if (ictx->num_key_fd == MP_MAX_KEY_FD) { - mp_tmsg(MSGT_INPUT, MSGL_ERR, "Too many key file descriptors, " - "cannot register file descriptor %d.\n", fd); - return 0; - } - if (select && fd < 0) { - mp_msg(MSGT_INPUT, MSGL_ERR, - "Invalid fd %d in mp_input_add_key_fd", fd); - return 0; - } - - ictx->key_fds[ictx->num_key_fd] = (struct input_fd){ - .fd = fd, - .read_func.key = read_func, - .close_func = close_func, - .no_select = !select, - .ctx = ctx, - }; - ictx->num_key_fd++; - - return 1; + mp_input_rm_fd(ictx, fd); } static int parse_cycle_dir(const struct m_option *opt, struct bstr name, @@ -1068,8 +1048,8 @@ static int read_cmd(struct input_fd *mp_fd, char **ret) // Get some data if needed/possible while (!mp_fd->got_cmd && !mp_fd->eof && (mp_fd->size - mp_fd->pos > 1)) { - int r = mp_fd->read_func.cmd(mp_fd->fd, mp_fd->buffer + mp_fd->pos, - mp_fd->size - 1 - mp_fd->pos); + int r = mp_fd->read_cmd(mp_fd->fd, mp_fd->buffer + mp_fd->pos, + mp_fd->size - 1 - mp_fd->pos); // Error ? if (r < 0) { switch (r) { @@ -1154,12 +1134,14 @@ static int default_cmd_func(int fd, char *buf, int l) } } +#ifndef __MINGW32__ static int read_wakeup(void *ctx, int fd) { char buf[100]; read(fd, buf, sizeof(buf)); return MP_INPUT_NOTHING; } +#endif static bool bind_matches_key(struct cmd_bind *bind, int n, const int *keys); @@ -1593,7 +1575,7 @@ static void read_cmd_fd(struct input_ctx *ictx, struct input_fd *cmd_fd) static void read_key_fd(struct input_ctx *ictx, struct input_fd *key_fd) { - int code = key_fd->read_func.key(key_fd->ctx, key_fd->fd); + int code = key_fd->read_key(key_fd->ctx, key_fd->fd); if (code >= 0 || code == MP_INPUT_RELEASE_ALL) { mp_input_feed_key(ictx, code); return; @@ -1609,50 +1591,38 @@ static void read_key_fd(struct input_ctx *ictx, struct input_fd *key_fd) } } -/** - * \param time time to wait at most for an event in milliseconds - */ -static void read_events(struct input_ctx *ictx, int time) +static void read_fd(struct input_ctx *ictx, struct input_fd *fd) { - if (ictx->num_key_down) { - time = FFMIN(time, 1000 / ictx->ar_rate); - time = FFMIN(time, ictx->ar_delay); + if (fd->read_cmd) { + read_cmd_fd(ictx, fd); + } else { + read_key_fd(ictx, fd); } - time = FFMAX(time, 0); - ictx->got_new_events = false; - struct input_fd *key_fds = ictx->key_fds; - struct input_fd *cmd_fds = ictx->cmd_fds; - for (int i = 0; i < ictx->num_key_fd; i++) - if (key_fds[i].dead) { - mp_input_rm_key_fd(ictx, key_fds[i].fd); - i--; - } else if (time && key_fds[i].no_select) - read_key_fd(ictx, &key_fds[i]); - for (int i = 0; i < ictx->num_cmd_fd; i++) - if (cmd_fds[i].dead || cmd_fds[i].eof) { - mp_input_rm_cmd_fd(ictx, cmd_fds[i].fd); +} + +static void remove_dead_fds(struct input_ctx *ictx) +{ + for (int i = 0; i < ictx->num_fds; i++) { + if (ictx->fds[i].dead) { + mp_input_rm_fd(ictx, ictx->fds[i].fd); i--; - } else if (time && cmd_fds[i].no_select) - read_cmd_fd(ictx, &cmd_fds[i]); - if (ictx->got_new_events) - time = 0; + } + } +} + #ifdef HAVE_POSIX_SELECT + +static void input_wait_read(struct input_ctx *ictx, int time) +{ fd_set fds; FD_ZERO(&fds); int max_fd = 0; - for (int i = 0; i < ictx->num_key_fd; i++) { - if (key_fds[i].no_select) - continue; - if (key_fds[i].fd > max_fd) - max_fd = key_fds[i].fd; - FD_SET(key_fds[i].fd, &fds); - } - for (int i = 0; i < ictx->num_cmd_fd; i++) { - if (cmd_fds[i].no_select) + for (int i = 0; i < ictx->num_fds; i++) { + if (!ictx->fds[i].select) continue; - if (cmd_fds[i].fd > max_fd) - max_fd = cmd_fds[i].fd; - FD_SET(cmd_fds[i].fd, &fds); + if (ictx->fds[i].fd > max_fd) + max_fd = ictx->fds[i].fd; + FD_SET(ictx->fds[i].fd, &fds); } struct timeval tv, *time_val; tv.tv_sec = time / 1000; @@ -1664,40 +1634,59 @@ static void read_events(struct input_ctx *ictx, int time) strerror(errno)); FD_ZERO(&fds); } + for (int i = 0; i < ictx->num_fds; i++) { + if (ictx->fds[i].select && !FD_ISSET(ictx->fds[i].fd, &fds)) + continue; + read_fd(ictx, &ictx->fds[i]); + } +} + #else + +static void input_wait_read(struct input_ctx *ictx, int time) +{ if (time > 0) mp_sleep_us(time * 1000); -#endif - - for (int i = 0; i < ictx->num_key_fd; i++) { -#ifdef HAVE_POSIX_SELECT - if (!key_fds[i].no_select && !FD_ISSET(key_fds[i].fd, &fds)) - continue; -#endif - read_key_fd(ictx, &key_fds[i]); - } + for (int i = 0; i < ictx->num_fds; i++) + read_fd(ictx, &ictx->fds[i]); +} - for (int i = 0; i < ictx->num_cmd_fd; i++) { -#ifdef HAVE_POSIX_SELECT - if (!cmd_fds[i].no_select && !FD_ISSET(cmd_fds[i].fd, &fds)) - continue; #endif - read_cmd_fd(ictx, &cmd_fds[i]); - } -} -/* To support blocking file descriptors we don't loop the read over - * every source until it's known to be empty. Instead we use this wrapper - * to run select() again. +/** + * \param time time to wait at most for an event in milliseconds */ -static void read_all_fd_events(struct input_ctx *ictx, int time) +static void read_events(struct input_ctx *ictx, int time) { + if (ictx->num_key_down) { + time = FFMIN(time, 1000 / ictx->ar_rate); + time = FFMIN(time, ictx->ar_delay); + } + time = FFMAX(time, 0); + while (1) { - read_events(ictx, time); + if (ictx->got_new_events) + time = 0; + ictx->got_new_events = false; + + remove_dead_fds(ictx); + + if (time) { + for (int i = 0; i < ictx->num_fds; i++) { + if (!ictx->fds[i].select) + read_fd(ictx, &ictx->fds[i]); + } + } + + if (ictx->got_new_events) + time = 0; + + input_wait_read(ictx, time); + + // Read until all input FDs are empty if (!ictx->got_new_events) - return; - time = 0; + break; } } @@ -1707,7 +1696,7 @@ static void read_all_events(struct input_ctx *ictx, int time) #ifdef CONFIG_COCOA cocoa_check_events(); #endif - read_all_fd_events(ictx, time); + read_events(ictx, time); } int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd) @@ -2209,13 +2198,9 @@ void mp_input_uninit(struct input_ctx *ictx, struct input_conf *input_conf) } #endif - 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 (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 < ictx->num_fds; i++) { + if (ictx->fds[i].close_func) + ictx->fds[i].close_func(ictx->fds[i].fd); } for (int i = 0; i < 2; i++) { if (ictx->wakeup_pipe[i] != -1) diff --git a/core/input/input.h b/core/input/input.h index da92efd373..1a0f2529ce 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -170,9 +170,6 @@ int mp_input_add_cmd_fd(struct input_ctx *ictx, int fd, int select, int read_func(int fd, char *dest, int size), int close_func(int fd)); -// This removes a cmd driver, you usually don't need to use it. -void mp_input_rm_cmd_fd(struct input_ctx *ictx, int fd); - /* The args are similar to the cmd version above, except you must give * a read_func, and it should return key codes (ASCII plus keycodes.h). */ diff --git a/core/m_struct.h b/core/m_struct.h index 6ddd221f1b..b0b0afe23d 100644 --- a/core/m_struct.h +++ b/ |