2008-12-13 18:28:00 +00:00
|
|
|
/*
|
|
|
|
* This file is part of MPlayer.
|
|
|
|
*
|
|
|
|
* MPlayer is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* MPlayer is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
2005-10-25 21:23:45 +00:00
|
|
|
#include "config.h"
|
2002-01-30 12:46:03 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2009-03-14 21:52:45 +00:00
|
|
|
#include <stdbool.h>
|
2002-01-30 12:46:03 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
2002-10-22 14:32:17 +00:00
|
|
|
#include <sys/stat.h>
|
2002-02-04 14:48:32 +00:00
|
|
|
#include <sys/time.h>
|
2002-01-30 12:46:03 +00:00
|
|
|
#include <fcntl.h>
|
2002-06-12 10:39:04 +00:00
|
|
|
#include <ctype.h>
|
2011-07-17 01:47:50 +00:00
|
|
|
#include <assert.h>
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2013-02-16 21:51:10 +00:00
|
|
|
#include <libavutil/avstring.h>
|
|
|
|
#include <libavutil/common.h>
|
|
|
|
|
2012-02-03 07:05:11 +00:00
|
|
|
#include "osdep/io.h"
|
2013-01-23 14:47:49 +00:00
|
|
|
#include "osdep/getch2.h"
|
2012-02-03 07:05:11 +00:00
|
|
|
|
2002-01-30 12:46:03 +00:00
|
|
|
#include "input.h"
|
2012-11-09 00:06:43 +00:00
|
|
|
#include "core/mp_fifo.h"
|
2011-04-25 06:43:59 +00:00
|
|
|
#include "keycodes.h"
|
2005-10-25 21:23:45 +00:00
|
|
|
#include "osdep/timer.h"
|
2012-11-09 00:06:43 +00:00
|
|
|
#include "core/mp_msg.h"
|
|
|
|
#include "core/m_config.h"
|
|
|
|
#include "core/m_option.h"
|
|
|
|
#include "core/path.h"
|
2008-04-30 04:15:52 +00:00
|
|
|
#include "talloc.h"
|
2012-11-09 00:06:43 +00:00
|
|
|
#include "core/options.h"
|
|
|
|
#include "core/bstr.h"
|
2012-08-01 19:50:24 +00:00
|
|
|
#include "stream/stream.h"
|
2013-02-16 21:51:10 +00:00
|
|
|
#include "core/mp_common.h"
|
2002-01-30 12:46:03 +00:00
|
|
|
|
|
|
|
#include "joystick.h"
|
|
|
|
|
2008-08-07 08:58:07 +00:00
|
|
|
#ifdef CONFIG_LIRC
|
2002-01-31 09:39:11 +00:00
|
|
|
#include "lirc.h"
|
|
|
|
#endif
|
|
|
|
|
2008-08-07 08:58:07 +00:00
|
|
|
#ifdef CONFIG_LIRCC
|
2003-05-30 18:23:55 +00:00
|
|
|
#include <lirc/lircc.h>
|
|
|
|
#endif
|
|
|
|
|
2013-06-02 15:39:05 +00:00
|
|
|
#ifdef CONFIG_COCOA
|
|
|
|
#include "osdep/macosx_events.h"
|
|
|
|
#endif
|
|
|
|
|
2013-03-30 18:29:45 +00:00
|
|
|
#define MP_MAX_KEY_DOWN 4
|
2011-07-16 15:17:48 +00:00
|
|
|
|
|
|
|
struct cmd_bind {
|
2013-06-22 22:07:45 +00:00
|
|
|
int keys[MP_MAX_KEY_DOWN];
|
|
|
|
int num_keys;
|
2011-04-25 08:38:46 +00:00
|
|
|
char *cmd;
|
2012-10-13 19:09:42 +00:00
|
|
|
char *location; // filename/line number of definition
|
2013-06-22 21:26:44 +00:00
|
|
|
bool is_builtin;
|
2012-10-13 19:09:42 +00:00
|
|
|
struct cmd_bind_section *owner;
|
2011-07-16 15:17:48 +00:00
|
|
|
};
|
2008-04-30 06:53:12 +00:00
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
struct key_name {
|
2011-04-25 08:38:46 +00:00
|
|
|
int key;
|
|
|
|
char *name;
|
2011-07-16 15:17:48 +00:00
|
|
|
};
|
2008-04-30 06:53:12 +00:00
|
|
|
|
2012-03-21 00:23:35 +00:00
|
|
|
/* This array defines all known commands.
|
|
|
|
* The first field is an id used to recognize the command.
|
|
|
|
* The second is the command name used in slave mode and input.conf.
|
|
|
|
* Then comes the definition of each argument, first mandatory arguments
|
|
|
|
* (ARG_INT, ARG_FLOAT, ARG_STRING) if any, then optional arguments
|
|
|
|
* (OARG_INT(default), etc) if any. The command will be given the default
|
|
|
|
* argument value if the user didn't give enough arguments to specify it.
|
|
|
|
* A command can take a maximum of MP_CMD_MAX_ARGS arguments (10).
|
|
|
|
*/
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
|
|
|
|
#define ARG_INT { .type = {"", NULL, &m_option_type_int} }
|
|
|
|
#define ARG_FLOAT { .type = {"", NULL, &m_option_type_float} }
|
|
|
|
#define ARG_STRING { .type = {"", NULL, &m_option_type_string} }
|
|
|
|
#define ARG_CHOICE(c) { .type = {"", NULL, &m_option_type_choice, \
|
|
|
|
M_CHOICES(c)} }
|
2013-02-24 20:16:23 +00:00
|
|
|
#define ARG_TIME { .type = {"", NULL, &m_option_type_time} }
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
|
|
|
|
#define OARG_FLOAT(def) { .type = {"", NULL, &m_option_type_float}, \
|
|
|
|
.optional = true, .v.f = def }
|
|
|
|
#define OARG_INT(def) { .type = {"", NULL, &m_option_type_int}, \
|
|
|
|
.optional = true, .v.i = def }
|
|
|
|
#define OARG_CHOICE(def, c) { .type = {"", NULL, &m_option_type_choice, \
|
|
|
|
M_CHOICES(c)}, \
|
|
|
|
.optional = true, .v.i = def }
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2012-10-12 07:21:26 +00:00
|
|
|
static int parse_cycle_dir(const struct m_option *opt, struct bstr name,
|
|
|
|
struct bstr param, void *dst);
|
|
|
|
static const struct m_option_type m_option_type_cycle_dir = {
|
|
|
|
.name = "up|down",
|
|
|
|
.parse = parse_cycle_dir,
|
|
|
|
};
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2008-01-13 16:13:54 +00:00
|
|
|
static const mp_cmd_t mp_cmds[] = {
|
2012-09-22 13:17:15 +00:00
|
|
|
{ MP_CMD_IGNORE, "ignore", },
|
2012-10-13 10:31:19 +00:00
|
|
|
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_RADIO_STEP_CHANNEL, "radio_step_channel", { ARG_INT } },
|
|
|
|
{ MP_CMD_RADIO_SET_CHANNEL, "radio_set_channel", { ARG_STRING } },
|
|
|
|
{ MP_CMD_RADIO_SET_FREQ, "radio_set_freq", { ARG_FLOAT } },
|
|
|
|
{ MP_CMD_RADIO_STEP_FREQ, "radio_step_freq", {ARG_FLOAT } },
|
2012-10-13 10:31:19 +00:00
|
|
|
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
{ MP_CMD_SEEK, "seek", {
|
2013-02-24 20:16:23 +00:00
|
|
|
ARG_TIME,
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
OARG_CHOICE(0, ({"relative", 0}, {"0", 0},
|
|
|
|
{"absolute-percent", 1}, {"1", 1},
|
|
|
|
{"absolute", 2}, {"2", 2})),
|
|
|
|
OARG_CHOICE(0, ({"default-precise", 0}, {"0", 0},
|
|
|
|
{"exact", 1}, {"1", 1},
|
|
|
|
{"keyframes", -1}, {"-1", -1})),
|
|
|
|
}},
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_SPEED_MULT, "speed_mult", { ARG_FLOAT } },
|
|
|
|
{ MP_CMD_QUIT, "quit", { OARG_INT(0) } },
|
core: add playback resume feature (manual/opt-in)
A "watch later" command is now mapped to Shift+Q. This quits the player
and stores the playback state in a config file in ~/.mpv/watch_later/.
When calling the player with the same file again, playback is resumed
at that time position.
It's also possible to make mpv save playback state always on quit with
the --save-position-on-quit option. Likewise, resuming can be disabled
with the --no-resume-playback option.
This also attempts to save some playback parameters, like fullscreen
state or track selection. This will unconditionally override config
settings and command line options (which is probably not what you would
expect, but in general nobody will really care about this). Some things
are not backed up, because that would cause various problems. Additional
subtitle files, video filters, etc. are not stored because that would be
too hard and fragile. Volume/mute state are not stored because it would
mess up if the system mixer is used, or if the system mixer was
readjusted in the meantime.
Basically, the tradeoff between perfect state restoration and
complexity/fragility makes it not worth to attempt to implement
it perfectly, even if the result is a little bit inconsistent.
2013-05-05 17:37:29 +00:00
|
|
|
{ MP_CMD_QUIT_WATCH_LATER, "quit_watch_later", },
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_STOP, "stop", },
|
|
|
|
{ MP_CMD_FRAME_STEP, "frame_step", },
|
core: add backstep support
Allows stepping back one frame via the frame_back_step inout command,
bound to "," by default.
This uses the precise seeking facility, and a perfect frame index built
on the fly. The index is built during playback and precise seeking, and
contains (as of this commit) the last 100 displayed or skipped frames.
This index is used to find the PTS of the previous frame, which is then
used as target for a precise seek. If no PTS is found, the core attempts
to do a seek before the current frame, and skip decoded frames until the
current frame is reached; this will create a sufficient index and the
normal backstep algorithm can be applied.
This can be rather slow. The worst case for backstepping is about the
same as the worst case for precise seeking if the previous frame can be
deduced from the index. If not, the worst case will be twice as slow.
There's also some minor danger that the index is incorrect in case
framedropping is involved. For framedropping due to --framedrop, this
problem is ignored (use of --framedrop is discouraged anyway). For
framedropping during precise seeking (done to make it faster), we try
to not add frames to the index that are produced when this can happen.
I'm not sure how well that works (or if the logic is sane), and it's
sure to break with some video filters. In the worst case, backstepping
might silently skip frames if you backstep after a user-initiated
precise seek. (Precise seeks to do indexing are not affected.)
Likewise, video filters that somehow change timing of frames and do not
do this in a deterministic way (i.e. if you seek to a position, frames
with different timings are produced than when the position is reached
during normal playback) will make backstepping silently jump to the
wrong frame. Enabling/disabling filters during playback (like for
example deinterlacing) will have similar bad effects.
2013-04-24 17:31:48 +00:00
|
|
|
{ MP_CMD_FRAME_BACK_STEP, "frame_back_step", },
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
{ MP_CMD_PLAYLIST_NEXT, "playlist_next", {
|
|
|
|
OARG_CHOICE(0, ({"weak", 0}, {"0", 0},
|
|
|
|
{"force", 1}, {"1", 1})),
|
|
|
|
}},
|
|
|
|
{ MP_CMD_PLAYLIST_PREV, "playlist_prev", {
|
|
|
|
OARG_CHOICE(0, ({"weak", 0}, {"0", 0},
|
|
|
|
{"force", 1}, {"1", 1})),
|
|
|
|
}},
|
2012-09-26 23:07:19 +00:00
|
|
|
{ MP_CMD_SUB_STEP, "sub_step", { ARG_INT } },
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_OSD, "osd", { OARG_INT(-1) } },
|
2012-10-11 00:24:13 +00:00
|
|
|
{ MP_CMD_PRINT_TEXT, "print_text", { ARG_STRING } },
|
2012-09-15 00:04:57 +00:00
|
|
|
{ MP_CMD_SHOW_TEXT, "show_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) } },
|
|
|
|
{ MP_CMD_SHOW_PROGRESS, "show_progress", },
|
2012-11-15 19:26:52 +00:00
|
|
|
{ MP_CMD_SUB_ADD, "sub_add", { ARG_STRING } },
|
|
|
|
{ MP_CMD_SUB_REMOVE, "sub_remove", { OARG_INT(-1) } },
|
|
|
|
{ MP_CMD_SUB_RELOAD, "sub_reload", { OARG_INT(-1) } },
|
2012-10-13 10:31:19 +00:00
|
|
|
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_TV_START_SCAN, "tv_start_scan", },
|
|
|
|
{ MP_CMD_TV_STEP_CHANNEL, "tv_step_channel", { ARG_INT } },
|
|
|
|
{ MP_CMD_TV_STEP_NORM, "tv_step_norm", },
|
|
|
|
{ MP_CMD_TV_STEP_CHANNEL_LIST, "tv_step_chanlist", },
|
|
|
|
{ MP_CMD_TV_SET_CHANNEL, "tv_set_channel", { ARG_STRING } },
|
|
|
|
{ MP_CMD_TV_LAST_CHANNEL, "tv_last_channel", },
|
|
|
|
{ MP_CMD_TV_SET_FREQ, "tv_set_freq", { ARG_FLOAT } },
|
|
|
|
{ MP_CMD_TV_STEP_FREQ, "tv_step_freq", { ARG_FLOAT } },
|
|
|
|
{ MP_CMD_TV_SET_NORM, "tv_set_norm", { ARG_STRING } },
|
2012-10-13 10:31:19 +00:00
|
|
|
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_DVB_SET_CHANNEL, "dvb_set_channel", { ARG_INT, ARG_INT } },
|
2012-10-13 10:31:19 +00:00
|
|
|
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
{ MP_CMD_SCREENSHOT, "screenshot", {
|
2012-10-20 21:58:02 +00:00
|
|
|
OARG_CHOICE(2, ({"video", 0},
|
|
|
|
{"window", 1},
|
2012-10-20 21:32:45 +00:00
|
|
|
{"subtitles", 2})),
|
2012-10-20 21:58:02 +00:00
|
|
|
OARG_CHOICE(0, ({"single", 0},
|
|
|
|
{"each-frame", 1})),
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
}},
|
|
|
|
{ MP_CMD_LOADFILE, "loadfile", {
|
|
|
|
ARG_STRING,
|
|
|
|
OARG_CHOICE(0, ({"replace", 0}, {"0", 0},
|
|
|
|
{"append", 1}, {"1", 1})),
|
|
|
|
}},
|
|
|
|
{ MP_CMD_LOADLIST, "loadlist", {
|
|
|
|
ARG_STRING,
|
|
|
|
OARG_CHOICE(0, ({"replace", 0}, {"0", 0},
|
|
|
|
{"append", 1}, {"1", 1})),
|
|
|
|
}},
|
mplayer: turn playtree into a list, and change per-file option handling
Summary:
- There is no playtree anymore. It's reduced to a simple list.
- Options are now always global. You can still have per-file options,
but these are optional and require special syntax.
- The slave command pt_step has been removed, and playlist_next
and playlist_prev added. (See etc/input.conf changes.)
This is a user visible incompatible change, and will break slave-mode
applications.
- The pt_clear slave command is renamed to playlist_clear.
- Playtree entries could have multiple files. This is not the case
anymore, and playlist entries have always exactly one entry. Whenever
something adds more than one file (like ASX playlists or dvd:// or
dvdnav:// on the command line), all files are added as separate
playlist entries.
Note that some of the changes are quite deep and violent. Expect
regressions.
The playlist parsing code in particular is of low quality. I didn't try
to improve it, and merely spent to least effort necessary to keep it
somehow working. (Especially ASX playlist handling.)
The playtree code was complicated and bloated. It was also barely used.
Most users don't even know that mplayer manages the playlist as tree,
or how to use it. The most obscure features was probably specifying a
tree on command line (with '{' and '}' to create/close tree nodes). It
filled the player code with complexity and confused users with weird
slave commands like pt_up.
Replace the playtree with a simple flat playlist. Playlist parsers that
actually return trees are changed to append all files to the playlist
pre-order.
It used to be the responsibility of the playtree code to change per-file
config options. Now this is done by the player core, and the playlist
code is free of such details.
Options are not per-file by default anymore. This was a very obscure and
complicated feature that confused even experienced users. Consider the
following command line:
mplayer file1.mkv file2.mkv --no-audio file3.mkv
This will disable the audio for file2.mkv only, because options are
per-file by default. To make the option affect all files, you're
supposed to put it before the first file.
This is bad, because normally you don't need per-file options. They are
very rarely needed, and the only reasonable use cases I can imagine are
use of the encode backend (mplayer encode branch), or for debugging. The
normal use case is made harder, and the feature is perceived as bug.
Even worse, correct usage is hard to explain for users.
Make all options global by default. The position of an option isn't
significant anymore (except for options that compensate each other,
consider --shuffle --no-shuffle).
One other important change is that no options are reset anymore if a
new file is started. If you change settings with slave mode commands,
they will not be changed by playing a new file. (Exceptions include
settings that are too file specific, like audio/subtitle stream
selection.)
There is still some need for per-file options. Debugging and encoding
are use cases that profit from per-file options. Per-file profiles (as
well as per-protocol and per-VO/AO options) need the implementation
related mechanisms to backup and restore options when the playback file
changes.
Simplify the save-slot stuff, which is possible because there is no
hierarchical play tree anymore. Now there's a simple backup field.
Add a way to specify per-file options on command line. Example:
mplayer f1.mkv -o0 --{ -o1 f2.mkv -o2 f3.mkv --} f4.mkv -o3
will have the following options per file set:
f1.mkv, f4.mkv: -o0 -o3
f2.mkv, f3.mkv: -o0 -o3 -o1 -o2
The options --{ and --} start and end per-file options. All files inside
the { } will be affected by the options equally (similar to how global
options and multiple files are handled). When playback of a file starts,
the per-file options are set according to the command line. When
playback ends, the per-file options are restored to the values when
playback started.
2012-07-31 19:33:26 +00:00
|
|
|
{ MP_CMD_PLAYLIST_CLEAR, "playlist_clear", },
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_RUN, "run", { ARG_STRING } },
|
2002-02-25 13:14:27 +00:00
|
|
|
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_KEYDOWN_EVENTS, "key_down_event", { ARG_INT } },
|
2012-09-09 00:08:08 +00:00
|
|
|
{ MP_CMD_SET, "set", { ARG_STRING, ARG_STRING } },
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_GET_PROPERTY, "get_property", { ARG_STRING } },
|
2012-09-22 04:15:36 +00:00
|
|
|
{ MP_CMD_ADD, "add", { ARG_STRING, OARG_FLOAT(0) } },
|
2012-10-12 07:21:26 +00:00
|
|
|
{ MP_CMD_CYCLE, "cycle", {
|
|
|
|
ARG_STRING,
|
|
|
|
{ .type = {"", NULL, &m_option_type_cycle_dir},
|
|
|
|
.optional = true,
|
|
|
|
.v.f = 1 },
|
|
|
|
}},
|
2012-03-21 00:23:35 +00:00
|
|
|
|
2013-06-22 23:28:28 +00:00
|
|
|
{ MP_CMD_ENABLE_INPUT_SECTION, "enable_section", {
|
|
|
|
ARG_STRING,
|
|
|
|
OARG_CHOICE(0, ({"default", 0},
|
|
|
|
{"exclusive", 1})),
|
|
|
|
}},
|
|
|
|
{ MP_CMD_DISABLE_INPUT_SECTION, "disable_section", { ARG_STRING } },
|
|
|
|
|
2012-03-21 00:23:35 +00:00
|
|
|
{ MP_CMD_AF_SWITCH, "af_switch", { ARG_STRING } },
|
|
|
|
{ MP_CMD_AF_ADD, "af_add", { ARG_STRING } },
|
|
|
|
{ MP_CMD_AF_DEL, "af_del", { ARG_STRING } },
|
|
|
|
{ MP_CMD_AF_CLR, "af_clr", },
|
|
|
|
{ MP_CMD_AF_CMDLINE, "af_cmdline", { ARG_STRING, ARG_STRING } },
|
2011-10-23 03:26:30 +00:00
|
|
|
|
2013-05-18 09:44:17 +00:00
|
|
|
{ MP_CMD_VF, "vf", { ARG_STRING, ARG_STRING } },
|
|
|
|
|
2012-07-31 23:06:59 +00:00
|
|
|
{ MP_CMD_VO_CMDLINE, "vo_cmdline", { ARG_STRING } },
|
|
|
|
|
2012-01-25 23:01:49 +00:00
|
|
|
{0}
|
2002-01-30 12:46:03 +00:00
|
|
|
};
|
|
|
|
|
2012-09-06 05:19:41 +00:00
|
|
|
// Map legacy commands to proper commands
|
|
|
|
struct legacy_cmd {
|
|
|
|
const char *old, *new;
|
|
|
|
};
|
|
|
|
static const struct legacy_cmd legacy_cmds[] = {
|
2012-09-22 04:15:36 +00:00
|
|
|
{"loop", "cycle loop"},
|
|
|
|
{"seek_chapter", "add chapter"},
|
|
|
|
{"switch_angle", "cycle angle"},
|
|
|
|
{"pause", "cycle pause"},
|
|
|
|
{"volume", "add volume"},
|
|
|
|
{"mute", "cycle mute"},
|
|
|
|
{"audio_delay", "add audio-delay"},
|
|
|
|
{"switch_audio", "cycle audio"},
|
|
|
|
{"balance", "add balance"},
|
2013-03-25 19:49:11 +00:00
|
|
|
{"vo_fullscreen", "cycle fullscreen"},
|
2012-09-22 04:15:36 +00:00
|
|
|
{"panscan", "add panscan"},
|
|
|
|
{"vo_ontop", "cycle ontop"},
|
|
|
|
{"vo_border", "cycle border"},
|
|
|
|
{"frame_drop", "cycle framedrop"},
|
|
|
|
{"gamma", "add gamma"},
|
|
|
|
{"brightness", "add brightness"},
|
|
|
|
{"contrast", "add contrast"},
|
|
|
|
{"saturation", "add saturation"},
|
|
|
|
{"hue", "add hue"},
|
|
|
|
{"switch_vsync", "cycle vsync"},
|
2012-11-15 19:26:52 +00:00
|
|
|
{"sub_load", "sub_add"},
|
2012-09-22 04:15:36 +00:00
|
|
|
{"sub_select", "cycle sub"},
|
|
|
|
{"sub_pos", "add sub-pos"},
|
|
|
|
{"sub_delay", "add sub-delay"},
|
|
|
|
{"sub_visibility", "cycle sub-visibility"},
|
|
|
|
{"forced_subs_only", "cycle sub-forced-only"},
|
|
|
|
{"sub_scale", "add sub-scale"},
|
|
|
|
{"ass_use_margins", "cycle ass-use-margins"},
|
|
|
|
{"tv_set_brightness", "add tv-brightness"},
|
|
|
|
{"tv_set_hue", "add tv-hue"},
|
|
|
|
{"tv_set_saturation", "add tv-saturation"},
|
|
|
|
{"tv_set_contrast", "add tv-contrast"},
|
|
|
|
{"step_property_osd", "cycle"},
|
|
|
|
{"step_property", "no-osd cycle"},
|
2012-09-14 23:10:59 +00:00
|
|
|
{"set_property", "no-osd set"},
|
|
|
|
{"set_property_osd", "set"},
|
2012-09-14 23:48:27 +00:00
|
|
|
{"speed_set", "set speed"},
|
2012-09-15 00:04:57 +00:00
|
|
|
{"osd_show_text", "show_text"},
|
|
|
|
{"osd_show_property_text", "show_text"},
|
|
|
|
{"osd_show_progression", "show_progress"},
|
2013-05-15 00:17:47 +00:00
|
|
|
{"show_chapters_osd", "show_text ${chapter-list}"},
|
|
|
|
{"!show_chapters", "show_text ${chapter-list}"},
|
|
|
|
{"show_tracks_osd", "show_text ${track-list}"},
|
|
|
|
{"!show_tracks", "show_text ${track-list}"},
|
|
|
|
{"!show_playlist", "show_text ${playlist}"},
|
|
|
|
|
2012-09-22 03:13:29 +00:00
|
|
|
// Approximate (can fail if user added additional whitespace)
|
2012-09-14 23:10:59 +00:00
|
|
|
{"pt_step 1", "playlist_next"},
|
|
|
|
{"pt_step -1", "playlist_prev"},
|
2012-09-22 03:13:29 +00:00
|
|
|
// Switch_ratio without argument resets aspect ratio
|
|
|
|
{"switch_ratio ", "set aspect "},
|
|
|
|
{"switch_ratio", "set aspect 0"},
|
2012-09-06 05:19:41 +00:00
|
|
|
{0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2003-07-09 01:42:19 +00:00
|
|
|
/// The names of the keys as used in input.conf
|
2002-03-19 13:30:16 +00:00
|
|
|
/// If you add some new keys, you also need to add them here
|
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
static const struct key_name key_names[] = {
|
2002-01-30 12:46:03 +00:00
|
|
|
{ ' ', "SPACE" },
|
2007-03-05 10:15:55 +00:00
|
|
|
{ '#', "SHARP" },
|
2013-02-12 00:34:04 +00:00
|
|
|
{ MP_KEY_ENTER, "ENTER" },
|
|
|
|
{ MP_KEY_TAB, "TAB" },
|
|
|
|
{ MP_KEY_BACKSPACE, "BS" },
|
|
|
|
{ MP_KEY_DELETE, "DEL" },
|
|
|
|
{ MP_KEY_INSERT, "INS" },
|
|
|
|
{ MP_KEY_HOME, "HOME" },
|
|
|
|
{ MP_KEY_END, "END" },
|
|
|
|
{ MP_KEY_PAGE_UP, "PGUP" },
|
|
|
|
{ MP_KEY_PAGE_DOWN, "PGDWN" },
|
|
|
|
{ MP_KEY_ESC, "ESC" },
|
|
|
|
{ MP_KEY_PRINT, "PRINT" },
|
|
|
|
{ MP_KEY_RIGHT, "RIGHT" },
|
|
|
|
{ MP_KEY_LEFT, "LEFT" },
|
|
|
|
{ MP_KEY_DOWN, "DOWN" },
|
|
|
|
{ MP_KEY_UP, "UP" },
|
|
|
|
{ MP_KEY_F+1, "F1" },
|
|
|
|
{ MP_KEY_F+2, "F2" },
|
|
|
|
{ MP_KEY_F+3, "F3" },
|
|
|
|
{ MP_KEY_F+4, "F4" },
|
|
|
|
{ MP_KEY_F+5, "F5" },
|
|
|
|
{ MP_KEY_F+6, "F6" },
|
|
|
|
{ MP_KEY_F+7, "F7" },
|
|
|
|
{ MP_KEY_F+8, "F8" },
|
|
|
|
{ MP_KEY_F+9, "F9" },
|
|
|
|
{ MP_KEY_F+10, "F10" },
|
|
|
|
{ MP_KEY_F+11, "F11" },
|
|
|
|
{ MP_KEY_F+12, "F12" },
|
|
|
|
{ MP_KEY_KP0, "KP0" },
|
|
|
|
{ MP_KEY_KP1, "KP1" },
|
|
|
|
{ MP_KEY_KP2, "KP2" },
|
|
|
|
{ MP_KEY_KP3, "KP3" },
|
|
|
|
{ MP_KEY_KP4, "KP4" },
|
|
|
|
{ MP_KEY_KP5, "KP5" },
|
|
|
|
{ MP_KEY_KP6, "KP6" },
|
|
|
|
{ MP_KEY_KP7, "KP7" },
|
|
|
|
{ MP_KEY_KP8, "KP8" },
|
|
|
|
{ MP_KEY_KP9, "KP9" },
|
|
|
|
{ MP_KEY_KPDEL, "KP_DEL" },
|
|
|
|
{ MP_KEY_KPDEC, "KP_DEC" },
|
|
|
|
{ MP_KEY_KPINS, "KP_INS" },
|
|
|
|
{ MP_KEY_KPENTER, "KP_ENTER" },
|
|
|
|
{ MP_MOUSE_BTN0, "MOUSE_BTN0" },
|
|
|
|
{ MP_MOUSE_BTN1, "MOUSE_BTN1" },
|
|
|
|
{ MP_MOUSE_BTN2, "MOUSE_BTN2" },
|
|
|
|
{ MP_MOUSE_BTN3, "MOUSE_BTN3" },
|
|
|
|
{ MP_MOUSE_BTN4, "MOUSE_BTN4" },
|
|
|
|
{ MP_MOUSE_BTN5, "MOUSE_BTN5" },
|
|
|
|
{ MP_MOUSE_BTN6, "MOUSE_BTN6" },
|
|
|
|
{ MP_MOUSE_BTN7, "MOUSE_BTN7" },
|
|
|
|
{ MP_MOUSE_BTN8, "MOUSE_BTN8" },
|
|
|
|
{ MP_MOUSE_BTN9, "MOUSE_BTN9" },
|
|
|
|
{ MP_MOUSE_BTN10, "MOUSE_BTN10" },
|
|
|
|
{ MP_MOUSE_BTN11, "MOUSE_BTN11" },
|
|
|
|
{ MP_MOUSE_BTN12, "MOUSE_BTN12" },
|
|
|
|
{ MP_MOUSE_BTN13, "MOUSE_BTN13" },
|
|
|
|
{ MP_MOUSE_BTN14, "MOUSE_BTN14" },
|
|
|
|
{ MP_MOUSE_BTN15, "MOUSE_BTN15" },
|
|
|
|
{ MP_MOUSE_BTN16, "MOUSE_BTN16" },
|
|
|
|
{ MP_MOUSE_BTN17, "MOUSE_BTN17" },
|
|
|
|
{ MP_MOUSE_BTN18, "MOUSE_BTN18" },
|
|
|
|
{ MP_MOUSE_BTN19, "MOUSE_BTN19" },
|
|
|
|
{ MP_MOUSE_BTN0_DBL, "MOUSE_BTN0_DBL" },
|
|
|
|
{ MP_MOUSE_BTN1_DBL, "MOUSE_BTN1_DBL" },
|
|
|
|
{ MP_MOUSE_BTN2_DBL, "MOUSE_BTN2_DBL" },
|
|
|
|
{ MP_MOUSE_BTN3_DBL, "MOUSE_BTN3_DBL" },
|
|
|
|
{ MP_MOUSE_BTN4_DBL, "MOUSE_BTN4_DBL" },
|
|
|
|
{ MP_MOUSE_BTN5_DBL, "MOUSE_BTN5_DBL" },
|
|
|
|
{ MP_MOUSE_BTN6_DBL, "MOUSE_BTN6_DBL" },
|
|
|
|
{ MP_MOUSE_BTN7_DBL, "MOUSE_BTN7_DBL" },
|
|
|
|
{ MP_MOUSE_BTN8_DBL, "MOUSE_BTN8_DBL" },
|
|
|
|
{ MP_MOUSE_BTN9_DBL, "MOUSE_BTN9_DBL" },
|
|
|
|
{ MP_MOUSE_BTN10_DBL, "MOUSE_BTN10_DBL" },
|
|
|
|
{ MP_MOUSE_BTN11_DBL, "MOUSE_BTN11_DBL" },
|
|
|
|
{ MP_MOUSE_BTN12_DBL, "MOUSE_BTN12_DBL" },
|
|
|
|
{ MP_MOUSE_BTN13_DBL, "MOUSE_BTN13_DBL" },
|
|
|
|
{ MP_MOUSE_BTN14_DBL, "MOUSE_BTN14_DBL" },
|
|
|
|
{ MP_MOUSE_BTN15_DBL, "MOUSE_BTN15_DBL" },
|
|
|
|
{ MP_MOUSE_BTN16_DBL, "MOUSE_BTN16_DBL" },
|
|
|
|
{ MP_MOUSE_BTN17_DBL, "MOUSE_BTN17_DBL" },
|
|
|
|
{ MP_MOUSE_BTN18_DBL, "MOUSE_BTN18_DBL" },
|
|
|
|
{ MP_MOUSE_BTN19_DBL, "MOUSE_BTN19_DBL" },
|
|
|
|
{ MP_JOY_AXIS1_MINUS, "JOY_UP" },
|
|
|
|
{ MP_JOY_AXIS1_PLUS, "JOY_DOWN" },
|
|
|
|
{ MP_JOY_AXIS0_MINUS, "JOY_LEFT" },
|
|
|
|
{ MP_JOY_AXIS0_PLUS, "JOY_RIGHT" },
|
|
|
|
|
|
|
|
{ MP_JOY_AXIS0_PLUS, "JOY_AXIS0_PLUS" },
|
|
|
|
{ MP_JOY_AXIS0_MINUS, "JOY_AXIS0_MINUS" },
|
|
|
|
{ MP_JOY_AXIS1_PLUS, "JOY_AXIS1_PLUS" },
|
|
|
|
{ MP_JOY_AXIS1_MINUS, "JOY_AXIS1_MINUS" },
|
|
|
|
{ MP_JOY_AXIS2_PLUS, "JOY_AXIS2_PLUS" },
|
|
|
|
{ MP_JOY_AXIS2_MINUS, "JOY_AXIS2_MINUS" },
|
|
|
|
{ MP_JOY_AXIS3_PLUS, "JOY_AXIS3_PLUS" },
|
|
|
|
{ MP_JOY_AXIS3_MINUS, "JOY_AXIS3_MINUS" },
|
|
|
|
{ MP_JOY_AXIS4_PLUS, "JOY_AXIS4_PLUS" },
|
|
|
|
{ MP_JOY_AXIS4_MINUS, "JOY_AXIS4_MINUS" },
|
|
|
|
{ MP_JOY_AXIS5_PLUS, "JOY_AXIS5_PLUS" },
|
|
|
|
{ MP_JOY_AXIS5_MINUS, "JOY_AXIS5_MINUS" },
|
|
|
|
{ MP_JOY_AXIS6_PLUS, "JOY_AXIS6_PLUS" },
|
|
|
|
{ MP_JOY_AXIS6_MINUS, "JOY_AXIS6_MINUS" },
|
|
|
|
{ MP_JOY_AXIS7_PLUS, "JOY_AXIS7_PLUS" },
|
|
|
|
{ MP_JOY_AXIS7_MINUS, "JOY_AXIS7_MINUS" },
|
|
|
|
{ MP_JOY_AXIS8_PLUS, "JOY_AXIS8_PLUS" },
|
|
|
|
{ MP_JOY_AXIS8_MINUS, "JOY_AXIS8_MINUS" },
|
|
|
|
{ MP_JOY_AXIS9_PLUS, "JOY_AXIS9_PLUS" },
|
|
|
|
{ MP_JOY_AXIS9_MINUS, "JOY_AXIS9_MINUS" },
|
|
|
|
|
|
|
|
{ MP_JOY_BTN0, "JOY_BTN0" },
|
|
|
|
{ MP_JOY_BTN1, "JOY_BTN1" },
|
|
|
|
{ MP_JOY_BTN2, "JOY_BTN2" },
|
|
|
|
{ MP_JOY_BTN3, "JOY_BTN3" },
|
|
|
|
{ MP_JOY_BTN4, "JOY_BTN4" },
|
|
|
|
{ MP_JOY_BTN5, "JOY_BTN5" },
|
|
|
|
{ MP_JOY_BTN6, "JOY_BTN6" },
|
|
|
|
{ MP_JOY_BTN7, "JOY_BTN7" },
|
|
|
|
{ MP_JOY_BTN8, "JOY_BTN8" },
|
|
|
|
{ MP_JOY_BTN9, "JOY_BTN9" },
|
|
|
|
|
2013-06-02 22:52:40 +00:00
|
|
|
{ MP_AR_PLAY, "AR_PLAY" },
|
|
|
|
{ MP_AR_PLAY_HOLD, "AR_PLAY_HOLD" },
|
|
|
|
{ MP_AR_CENTER, "AR_CENTER" },
|
|
|
|
{ MP_AR_CENTER_HOLD, "AR_CENTER_HOLD" },
|
|
|
|
{ MP_AR_NEXT, "AR_NEXT" },
|
|
|
|
{ MP_AR_NEXT_HOLD, "AR_NEXT_HOLD" },
|
|
|
|
{ MP_AR_PREV, "AR_PREV" },
|
|
|
|
{ MP_AR_PREV_HOLD, "AR_PREV_HOLD" },
|
|
|
|
{ MP_AR_MENU, "AR_MENU" },
|
|
|
|
{ MP_AR_MENU_HOLD, "AR_MENU_HOLD" },
|
|
|
|
{ MP_AR_VUP, "AR_VUP" },
|
|
|
|
{ MP_AR_VUP_HOLD, "AR_VUP_HOLD" },
|
|
|
|
{ MP_AR_VDOWN, "AR_VDOWN" },
|
|
|
|
{ MP_AR_VDOWN_HOLD, "AR_VDOWN_HOLD" },
|
|
|
|
|
2013-06-04 20:12:23 +00:00
|
|
|
{ MP_MK_PLAY, "MK_PLAY" },
|
|
|
|
{ MP_MK_PREV, "MK_PREV" },
|
|
|
|
{ MP_MK_NEXT, "MK_NEXT" },
|
|
|
|
|
2013-02-12 00:34:04 +00:00
|
|
|
{ MP_KEY_POWER, "POWER" },
|
|
|
|
{ MP_KEY_MENU, "MENU" },
|
|
|
|
{ MP_KEY_PLAY, "PLAY" },
|
|
|
|
{ MP_KEY_PAUSE, "PAUSE" },
|
|
|
|
{ MP_KEY_PLAYPAUSE, "PLAYPAUSE" },
|
|
|
|
{ MP_KEY_STOP, "STOP" },
|
|
|
|
{ MP_KEY_FORWARD, "FORWARD" },
|
|
|
|
{ MP_KEY_REWIND, "REWIND" },
|
|
|
|
{ MP_KEY_NEXT, "NEXT" },
|
|
|
|
{ MP_KEY_PREV, "PREV" },
|
|
|
|
{ MP_KEY_VOLUME_UP, "VOLUME_UP" },
|
|
|
|
{ MP_KEY_VOLUME_DOWN, "VOLUME_DOWN" },
|
|
|
|
{ MP_KEY_MUTE, "MUTE" },
|
2005-11-02 21:50:55 +00:00
|
|
|
|
|
|
|
// These are kept for backward compatibility
|
2013-02-12 00:34:04 +00:00
|
|
|
{ MP_KEY_PAUSE, "XF86_PAUSE" },
|
|
|
|
{ MP_KEY_STOP, "XF86_STOP" },
|
|
|
|
{ MP_KEY_PREV, "XF86_PREV" },
|
|
|
|
{ MP_KEY_NEXT, "XF86_NEXT" },
|
2005-11-02 21:50:55 +00:00
|
|
|
|
2013-06-19 16:19:45 +00:00
|
|
|
{ MP_KEY_CLOSE_WIN, "CLOSE_WIN" },
|
|
|
|
{ MP_KEY_MOUSE_MOVE, "MOUSE_MOVE" },
|
|
|
|
{ MP_KEY_MOUSE_LEAVE, "MOUSE_LEAVE" },
|
2003-04-04 15:04:26 +00:00
|
|
|
|
2002-01-30 12:46:03 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
struct key_name modifier_names[] = {
|
2013-02-12 00:34:04 +00:00
|
|
|
{ MP_KEY_MODIFIER_SHIFT, "Shift" },
|
|
|
|
{ MP_KEY_MODIFIER_CTRL, "Ctrl" },
|
|
|
|
{ MP_KEY_MODIFIER_ALT, "Alt" },
|
|
|
|
{ MP_KEY_MODIFIER_META, "Meta" },
|
2010-12-19 10:12:20 +00:00
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
2002-01-30 12:46:03 +00:00
|
|
|
#ifndef MP_MAX_KEY_FD
|
|
|
|
#define MP_MAX_KEY_FD 10
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MP_MAX_CMD_FD
|
|
|
|
#define MP_MAX_CMD_FD 10
|
|
|
|
#endif
|
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
struct input_fd {
|
2011-04-25 08:38:46 +00:00
|
|
|
int fd;
|
|
|
|
union {
|
2011-07-16 15:17:48 +00:00
|
|
|
int (*key)(void *ctx, int fd);
|
|
|
|
int (*cmd)(int fd, char *dest, int size);
|
2011-04-25 08:38:46 +00:00
|
|
|
} read_func;
|
2011-07-16 15:17:48 +00:00
|
|
|
int (*close_func)(int fd);
|
2011-04-25 08:38:46 +00:00
|
|
|
void *ctx;
|
|
|
|
unsigned eof : 1;
|
|
|
|
unsigned drop : 1;
|
|
|
|
unsigned dead : 1;
|
|
|
|
unsigned got_cmd : 1;
|
|
|
|
unsigned no_select : 1;
|
|
|
|
// These fields are for the cmd fds.
|
|
|
|
char *buffer;
|
|
|
|
int pos, size;
|
2011-07-16 15:17:48 +00:00
|
|
|
};
|
2002-11-14 23:41:44 +00:00
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
struct cmd_bind_section {
|
2013-06-22 22:40:35 +00:00
|
|
|
struct cmd_bind *binds;
|
|
|
|
int num_binds;
|
2011-04-25 08:38:46 +00:00
|
|
|
char *section;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
struct mp_rect mouse_area; // set at runtime, if at all
|
|
|
|
bool mouse_area_set; // mouse_area is valid and should be tested
|
2011-07-16 15:17:48 +00:00
|
|
|
struct cmd_bind_section *next;
|
2007-06-07 18:06:53 +00:00
|
|
|
};
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
#define MAX_ACTIVE_SECTIONS 5
|
|
|
|
|
|
|
|
struct active_section {
|
|
|
|
char *name;
|
|
|
|
int flags;
|
|
|
|
};
|
|
|
|
|
2011-07-17 01:47:50 +00:00
|
|
|
struct cmd_queue {
|
|
|
|
struct mp_cmd *first;
|
|
|
|
};
|
|
|
|
|
2008-04-30 04:15:52 +00:00
|
|
|
struct input_ctx {
|
|
|
|
// Autorepeat stuff
|
|
|
|
short ar_state;
|
2013-05-25 16:31:06 +00:00
|
|
|
int64_t last_ar;
|
2008-04-30 15:57:02 +00:00
|
|
|
// Autorepeat config
|
|
|
|
unsigned int ar_delay;
|
|
|
|
unsigned int ar_rate;
|
2011-07-17 01:47:50 +00:00
|
|
|
// Maximum number of queued commands from keypresses (limit to avoid
|
|
|
|
// repeated slow commands piling up)
|
|
|
|
int key_fifo_size;
|
2008-04-30 05:56:45 +00:00
|
|
|
|
2008-04-30 07:21:50 +00:00
|
|
|
// these are the keys currently down
|
|
|
|
int key_down[MP_MAX_KEY_DOWN];
|
|
|
|
unsigned int num_key_down;
|
2013-05-25 16:31:06 +00:00
|
|
|
int64_t last_key_down;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
struct mp_cmd *current_down_cmd;
|
|
|
|
|
|
|
|
// Mouse position on the consumer side (as command.c sees it)
|
|
|
|
int mouse_x, mouse_y;
|
2013-06-19 16:19:45 +00:00
|
|
|
char *mouse_section; // last section to receive mouse event
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
|
|
|
|
// Mouse position on the producer side (as the VO sees it)
|
|
|
|
// Unlike mouse_x/y, this can be used to resolve mouse click bindings.
|
|
|
|
int mouse_vo_x, mouse_vo_y;
|
2008-04-30 07:21:50 +00:00
|
|
|
|
2012-10-13 19:10:20 +00:00
|
|
|
bool test;
|
|
|
|
|
2009-03-31 23:26:34 +00:00
|
|
|
bool default_bindings;
|
2008-04-30 05:56:45 +00:00
|
|
|
// List of command binding sections
|
2011-07-16 15:17:48 +00:00
|
|
|
struct cmd_bind_section *cmd_bind_sections;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
|
|
|
|
// List currently active command sections
|
|
|
|
struct active_section active_sections[MAX_ACTIVE_SECTIONS];
|
|
|
|
int num_active_sections;
|
2008-04-30 08:06:55 +00:00
|
|
|
|
2011-07-17 01:47:50 +00:00
|
|
|
// Used to track whether we managed to read something while checking
|
|
|
|
// events sources. If yes, the sources may have more queued.
|
|
|
|
bool got_new_events;
|
|
|
|
|
2013-05-25 16:31:06 +00:00
|
|
|
unsigned int mouse_event_counter;
|
2013-05-16 21:17:46 +00:00
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
struct input_fd key_fds[MP_MAX_KEY_FD];
|
2008-04-30 08:06:55 +00:00
|
|
|
unsigned int num_key_fd;
|
2008-04-30 10:00:59 +00:00
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
struct input_fd cmd_fds[MP_MAX_CMD_FD];
|
2008-04-30 10:14:03 +00:00
|
|
|
unsigned int num_cmd_fd;
|
|
|
|
|
2011-07-17 01:47:50 +00:00
|
|
|
struct cmd_queue key_cmd_queue;
|
|
|
|
struct cmd_queue control_cmd_queue;
|
2012-03-25 19:58:48 +00:00
|
|
|
|
|
|
|
int wakeup_pipe[2];
|
2008-04-30 04:15:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-01-08 21:40:44 +00:00
|
|
|
int async_quit_request;
|
|
|
|
|
2012-05-07 20:16:20 +00:00
|
|
|
static int print_key_list(m_option_t *cfg, char *optname, char *optparam);
|
|
|
|
static int print_cmd_list(m_option_t *cfg, char *optname, char *optparam);
|
2002-03-20 13:30:57 +00:00
|
|
|
|
2013-03-01 10:27:59 +00:00
|
|
|
#define OPT_BASE_STRUCT struct MPOpts
|
|
|
|
|
2002-03-19 13:30:16 +00:00
|
|
|
// Our command line options
|
2008-04-26 13:35:40 +00:00
|
|
|
static const m_option_t input_conf[] = {
|
2013-02-08 22:52:06 +00:00
|
|
|
OPT_STRING("conf", input.config_file, CONF_GLOBAL),
|
2011-04-25 08:38:46 +00:00
|
|
|
OPT_INT("ar-delay", input.ar_delay, CONF_GLOBAL),
|
2008-04-30 15:57:02 +00:00
|
|
|
OPT_INT("ar-rate", input.ar_rate, CONF_GLOBAL),
|
2012-08-05 21:34:28 +00:00
|
|
|
{ "keylist", print_key_list, CONF_TYPE_PRINT_FUNC, CONF_GLOBAL | CONF_NOCFG },
|
|
|
|
{ "cmdlist", print_cmd_list, CONF_TYPE_PRINT_FUNC, CONF_GLOBAL | CONF_NOCFG },
|
2008-04-30 15:57:02 +00:00
|
|
|
OPT_STRING("js-dev", input.js_dev, CONF_GLOBAL),
|
|
|
|
OPT_STRING("file", input.in_file, CONF_GLOBAL),
|
2013-02-08 20:09:18 +00:00
|
|
|
OPT_FLAG("default-bindings", input.default_bindings, CONF_GLOBAL),
|
|
|
|
OPT_FLAG("test", input.test, CONF_GLOBAL),
|
2011-04-25 08:38:46 +00:00
|
|
|
{ NULL, NULL, 0, 0, 0, 0, NULL}
|
2002-02-11 11:42:08 +00:00
|
|
|
};
|
|
|
|
|
2008-04-26 13:35:40 +00:00
|
|
|
static const m_option_t mp_input_opts[] = {
|
2011-07-07 21:41:42 +00:00
|
|
|
{ "input", (void *)&input_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
|
2013-02-08 20:09:18 +00:00
|
|
|
OPT_FLAG("joystick", input.use_joystick, CONF_GLOBAL),
|
|
|
|
OPT_FLAG("lirc", input.use_lirc, CONF_GLOBAL),
|
|
|
|
OPT_FLAG("lircc", input.use_lircc, CONF_GLOBAL),
|
2013-06-03 21:02:16 +00:00
|
|
|
#ifdef CONFIG_COCOA
|
2013-06-02 22:52:40 +00:00
|
|
|
OPT_FLAG("ar", input.use_ar, CONF_GLOBAL),
|
2013-06-04 20:12:23 +00:00
|
|
|
OPT_FLAG("media-keys", input.use_media_keys, CONF_GLOBAL),
|
2013-06-03 21:02:16 +00:00
|
|
|
#endif
|
2011-04-25 08:38:46 +00:00
|
|
|
{ NULL, NULL, 0, 0, 0, 0, NULL}
|
2002-02-11 11:42:08 +00:00
|
|
|
};
|
2002-02-08 18:10:56 +00:00
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
static int default_cmd_func(int fd, char *buf, int l);
|
2002-10-25 16:06:25 +00:00
|
|
|
|
2012-08-01 20:52:28 +00:00
|
|
|
static const char builtin_input_conf[] =
|
2012-11-09 00:06:43 +00:00
|
|
|
#include "core/input/input_conf.h"
|
2012-08-01 20:52:28 +00:00
|
|
|
;
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
static bool test_rect(struct mp_rect *rc, int x, int y)
|
|
|
|
{
|
|
|
|
return x >= rc->x0 && y >= rc->y0 && x < rc->x1 && y < rc->y1;
|
|
|
|
}
|
|
|
|
|
2011-06-29 05:49:01 +00:00
|
|
|
static char *get_key_name(int key, char *ret)
|
2010-12-19 10:12:20 +00:00
|
|
|
{
|
|
|
|
for (int i = 0; modifier_names[i].name; i++) {
|
|
|
|
if (modifier_names[i].key & key) {
|
|
|
|
ret = talloc_asprintf_append_buffer(ret, "%s+",
|
|
|
|
modifier_names[i].name);
|
|
|
|
key -= modifier_names[i].key;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; key_names[i].name != NULL; i++) {
|
|
|
|
if (key_names[i].key == key)
|
|
|
|
return talloc_asprintf_append_buffer(ret, "%s", key_names[i].name);
|
|
|
|
}
|
|
|
|
|
2012-01-14 13:09:26 +00:00
|
|
|
// printable, and valid unicode range
|
|
|
|
if (key >= 32 && key <= 0x10FFFF)
|
2013-02-16 21:51:10 +00:00
|
|
|
return mp_append_utf8_buffer(ret, key);
|
2002-02-11 11:42:08 +00:00
|
|
|
|
2010-12-19 10:12:20 +00:00
|
|
|
// Print the hex key code
|
|
|
|
return talloc_asprintf_append_buffer(ret, "%#-8x", key);
|
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2011-06-29 05:49:01 +00:00
|
|
|
static char *get_key_combo_name(int *keys, int max)
|
|
|
|
{
|
|
|
|
char *ret = talloc_strdup(NULL, "");
|
|
|
|
while (1) {
|
|
|
|
ret = get_key_name(*keys, ret);
|
|
|
|
if (--max && *++keys)
|
2013-03-19 12:02:42 +00:00
|
|
|
ret = talloc_asprintf_append_buffer(ret, "-");
|
2011-06-29 05:49:01 +00:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
mplayer: turn playtree into a list, and change per-file option handling
Summary:
- There is no playtree anymore. It's reduced to a simple list.
- Options are now always global. You can still have per-file options,
but these are optional and require special syntax.
- The slave command pt_step has been removed, and playlist_next
and playlist_prev added. (See etc/input.conf changes.)
This is a user visible incompatible change, and will break slave-mode
applications.
- The pt_clear slave command is renamed to playlist_clear.
- Playtree entries could have multiple files. This is not the case
anymore, and playlist entries have always exactly one entry. Whenever
something adds more than one file (like ASX playlists or dvd:// or
dvdnav:// on the command line), all files are added as separate
playlist entries.
Note that some of the changes are quite deep and violent. Expect
regressions.
The playlist parsing code in particular is of low quality. I didn't try
to improve it, and merely spent to least effort necessary to keep it
somehow working. (Especially ASX playlist handling.)
The playtree code was complicated and bloated. It was also barely used.
Most users don't even know that mplayer manages the playlist as tree,
or how to use it. The most obscure features was probably specifying a
tree on command line (with '{' and '}' to create/close tree nodes). It
filled the player code with complexity and confused users with weird
slave commands like pt_up.
Replace the playtree with a simple flat playlist. Playlist parsers that
actually return trees are changed to append all files to the playlist
pre-order.
It used to be the responsibility of the playtree code to change per-file
config options. Now this is done by the player core, and the playlist
code is free of such details.
Options are not per-file by default anymore. This was a very obscure and
complicated feature that confused even experienced users. Consider the
following command line:
mplayer file1.mkv file2.mkv --no-audio file3.mkv
This will disable the audio for file2.mkv only, because options are
per-file by default. To make the option affect all files, you're
supposed to put it before the first file.
This is bad, because normally you don't need per-file options. They are
very rarely needed, and the only reasonable use cases I can imagine are
use of the encode backend (mplayer encode branch), or for debugging. The
normal use case is made harder, and the feature is perceived as bug.
Even worse, correct usage is hard to explain for users.
Make all options global by default. The position of an option isn't
significant anymore (except for options that compensate each other,
consider --shuffle --no-shuffle).
One other important change is that no options are reset anymore if a
new file is started. If you change settings with slave mode commands,
they will not be changed by playing a new file. (Exceptions include
settings that are too file specific, like audio/subtitle stream
selection.)
There is still some need for per-file options. Debugging and encoding
are use cases that profit from per-file options. Per-file profiles (as
well as per-protocol and per-VO/AO options) need the implementation
related mechanisms to backup and restore options when the playback file
changes.
Simplify the save-slot stuff, which is possible because there is no
hierarchical play tree anymore. Now there's a simple backup field.
Add a way to specify per-file options on command line. Example:
mplayer f1.mkv -o0 --{ -o1 f2.mkv -o2 f3.mkv --} f4.mkv -o3
will have the following options per file set:
f1.mkv, f4.mkv: -o0 -o3
f2.mkv, f3.mkv: -o0 -o3 -o1 -o2
The options --{ and --} start and end per-file options. All files inside
the { } will be affected by the options equally (similar to how global
options and multiple files are handled). When playback of a file starts,
the per-file options are set according to the command line. When
playback ends, the per-file options are restored to the values when
playback started.
2012-07-31 19:33:26 +00:00
|
|
|
bool mp_input_is_abort_cmd(int cmd_id)
|
2011-07-17 01:47:50 +00:00
|
|
|
{
|
|
|
|
switch (cmd_id) {
|
|
|
|
case MP_CMD_QUIT:
|
mplayer: turn playtree into a list, and change per-file option handling
Summary:
- There is no playtree anymore. It's reduced to a simple list.
- Options are now always global. You can still have per-file options,
but these are optional and require special syntax.
- The slave command pt_step has been removed, and playlist_next
and playlist_prev added. (See etc/input.conf changes.)
This is a user visible incompatible change, and will break slave-mode
applications.
- The pt_clear slave command is renamed to playlist_clear.
- Playtree entries could have multiple files. This is not the case
anymore, and playlist entries have always exactly one entry. Whenever
something adds more than one file (like ASX playlists or dvd:// or
dvdnav:// on the command line), all files are added as separate
playlist entries.
Note that some of the changes are quite deep and violent. Expect
regressions.
The playlist parsing code in particular is of low quality. I didn't try
to improve it, and merely spent to least effort necessary to keep it
somehow working. (Especially ASX playlist handling.)
The playtree code was complicated and bloated. It was also barely used.
Most users don't even know that mplayer manages the playlist as tree,
or how to use it. The most obscure features was probably specifying a
tree on command line (with '{' and '}' to create/close tree nodes). It
filled the player code with complexity and confused users with weird
slave commands like pt_up.
Replace the playtree with a simple flat playlist. Playlist parsers that
actually return trees are changed to append all files to the playlist
pre-order.
It used to be the responsibility of the playtree code to change per-file
config options. Now this is done by the player core, and the playlist
code is free of such details.
Options are not per-file by default anymore. This was a very obscure and
complicated feature that confused even experienced users. Consider the
following command line:
mplayer file1.mkv file2.mkv --no-audio file3.mkv
This will disable the audio for file2.mkv only, because options are
per-file by default. To make the option affect all files, you're
supposed to put it before the first file.
This is bad, because normally you don't need per-file options. They are
very rarely needed, and the only reasonable use cases I can imagine are
use of the encode backend (mplayer encode branch), or for debugging. The
normal use case is made harder, and the feature is perceived as bug.
Even worse, correct usage is hard to explain for users.
Make all options global by default. The position of an option isn't
significant anymore (except for options that compensate each other,
consider --shuffle --no-shuffle).
One other important change is that no options are reset anymore if a
new file is started. If you change settings with slave mode commands,
they will not be changed by playing a new file. (Exceptions include
settings that are too file specific, like audio/subtitle stream
selection.)
There is still some need for per-file options. Debugging and encoding
are use cases that profit from per-file options. Per-file profiles (as
well as per-protocol and per-VO/AO options) need the implementation
related mechanisms to backup and restore options when the playback file
changes.
Simplify the save-slot stuff, which is possible because there is no
hierarchical play tree anymore. Now there's a simple backup field.
Add a way to specify per-file options on command line. Example:
mplayer f1.mkv -o0 --{ -o1 f2.mkv -o2 f3.mkv --} f4.mkv -o3
will have the following options per file set:
f1.mkv, f4.mkv: -o0 -o3
f2.mkv, f3.mkv: -o0 -o3 -o1 -o2
The options --{ and --} start and end per-file options. All files inside
the { } will be affected by the options equally (similar to how global
options and multiple files are handled). When playback of a file starts,
the per-file options are set according to the command line. When
playback ends, the per-file options are restored to the values when
playback started.
2012-07-31 19:33:26 +00:00
|
|
|
case MP_CMD_PLAYLIST_NEXT:
|
|
|
|
case MP_CMD_PLAYLIST_PREV:
|
2011-07-17 01:47:50 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-01-18 01:35:40 +00:00
|
|
|
static int queue_count_cmds(struct cmd_queue *queue)
|
2011-07-17 01:47:50 +00:00
|
|
|
{
|
2012-01-18 01:35:40 +00:00
|
|
|
int res = 0;
|
|
|
|
for (struct mp_cmd *cmd = queue->first; cmd; cmd = cmd->queue_next)
|
|
|
|
res++;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool queue_has_abort_cmds(struct cmd_queue *queue)
|
|
|
|
{
|
|
|
|
for (struct mp_cmd *cmd = queue->first; cmd; cmd = cmd->queue_next) {
|
mplayer: turn playtree into a list, and change per-file option handling
Summary:
- There is no playtree anymore. It's reduced to a simple list.
- Options are now always global. You can still have per-file options,
but these are optional and require special syntax.
- The slave command pt_step has been removed, and playlist_next
and playlist_prev added. (See etc/input.conf changes.)
This is a user visible incompatible change, and will break slave-mode
applications.
- The pt_clear slave command is renamed to playlist_clear.
- Playtree entries could have multiple files. This is not the case
anymore, and playlist entries have always exactly one entry. Whenever
something adds more than one file (like ASX playlists or dvd:// or
dvdnav:// on the command line), all files are added as separate
playlist entries.
Note that some of the changes are quite deep and violent. Expect
regressions.
The playlist parsing code in particular is of low quality. I didn't try
to improve it, and merely spent to least effort necessary to keep it
somehow working. (Especially ASX playlist handling.)
The playtree code was complicated and bloated. It was also barely used.
Most users don't even know that mplayer manages the playlist as tree,
or how to use it. The most obscure features was probably specifying a
tree on command line (with '{' and '}' to create/close tree nodes). It
filled the player code with complexity and confused users with weird
slave commands like pt_up.
Replace the playtree with a simple flat playlist. Playlist parsers that
actually return trees are changed to append all files to the playlist
pre-order.
It used to be the responsibility of the playtree code to change per-file
config options. Now this is done by the player core, and the playlist
code is free of such details.
Options are not per-file by default anymore. This was a very obscure and
complicated feature that confused even experienced users. Consider the
following command line:
mplayer file1.mkv file2.mkv --no-audio file3.mkv
This will disable the audio for file2.mkv only, because options are
per-file by default. To make the option affect all files, you're
supposed to put it before the first file.
This is bad, because normally you don't need per-file options. They are
very rarely needed, and the only reasonable use cases I can imagine are
use of the encode backend (mplayer encode branch), or for debugging. The
normal use case is made harder, and the feature is perceived as bug.
Even worse, correct usage is hard to explain for users.
Make all options global by default. The position of an option isn't
significant anymore (except for options that compensate each other,
consider --shuffle --no-shuffle).
One other important change is that no options are reset anymore if a
new file is started. If you change settings with slave mode commands,
they will not be changed by playing a new file. (Exceptions include
settings that are too file specific, like audio/subtitle stream
selection.)
There is still some need for per-file options. Debugging and encoding
are use cases that profit from per-file options. Per-file profiles (as
well as per-protocol and per-VO/AO options) need the implementation
related mechanisms to backup and restore options when the playback file
changes.
Simplify the save-slot stuff, which is possible because there is no
hierarchical play tree anymore. Now there's a simple backup field.
Add a way to specify per-file options on command line. Example:
mplayer f1.mkv -o0 --{ -o1 f2.mkv -o2 f3.mkv --} f4.mkv -o3
will have the following options per file set:
f1.mkv, f4.mkv: -o0 -o3
f2.mkv, f3.mkv: -o0 -o3 -o1 -o2
The options --{ and --} start and end per-file options. All files inside
the { } will be affected by the options equally (similar to how global
options and multiple files are handled). When playback of a file starts,
the per-file options are set according to the command line. When
playback ends, the per-file options are restored to the values when
playback started.
2012-07-31 19:33:26 +00:00
|
|
|
if (mp_input_is_abort_cmd(cmd->id))
|
2012-01-18 01:35:40 +00:00
|
|
|
return true;
|
2011-10-24 00:28:56 +00:00
|
|
|
}
|
2012-01-18 01:35:40 +00:00
|
|
|
return false;
|
2011-10-24 00:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void queue_remove(struct cmd_queue *queue, struct mp_cmd *cmd)
|
|
|
|
{
|
|
|
|
struct mp_cmd **p_prev = &queue->first;
|
|
|
|
while (*p_prev != cmd) {
|
|
|
|
p_prev = &(*p_prev)->queue_next;
|
|
|
|
}
|
|
|
|
// if this fails, cmd was not in the queue
|
|
|
|
assert(*p_prev == cmd);
|
|
|
|
*p_prev = cmd->queue_next;
|
|
|
|
}
|
|
|
|
|
2011-07-17 01:47:50 +00:00
|
|
|
static void queue_add(struct cmd_queue *queue, struct mp_cmd *cmd,
|
|
|
|
bool at_head)
|
|
|
|
{
|
2011-10-24 00:28:56 +00:00
|
|
|
if (at_head) {
|
2011-07-17 01:47:50 +00:00
|
|
|
cmd->queue_next = queue->first;
|
|
|
|
queue->first = cmd;
|
|
|
|
} else {
|
2011-10-24 00:28:56 +00:00
|
|
|
struct mp_cmd **p_prev = &queue->first;
|
|
|
|
while (*p_prev)
|
|
|
|
p_prev = &(*p_prev)->queue_next;
|
|
|
|
*p_prev = cmd;
|
|
|
|
cmd->queue_next = NULL;
|
2011-07-17 01:47:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-30 10:14:03 +00:00
|
|
|
int mp_input_add_cmd_fd(struct input_ctx *ictx, int fd, int select,
|
2011-07-16 15:17:48 +00:00
|
|
|
int read_func(int fd, char *dest, int size),
|
|
|
|
int close_func(int fd))
|
2008-04-30 10:14:03 +00:00
|
|
|
{
|
2011-04-25 08:38:46 +00:00
|
|
|
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) {
|
|
|
|
mp_msg(MSGT_INPUT, MSGL_ERR,
|
|
|
|
"Invalid fd %d in mp_input_add_cmd_fd", fd);
|
|
|
|
return 0;
|
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
ictx->cmd_fds[ictx->num_cmd_fd] = (struct input_fd){
|
2011-04-25 08:38:46 +00:00
|
|
|
.fd = fd,
|
|
|
|
.read_func.cmd = read_func ? read_func : default_cmd_func,
|
|
|
|
.close_func = close_func,
|
|
|
|
.no_select = !select
|
|
|
|
};
|
|
|
|
ictx->num_cmd_fd++;
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
return 1;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2008-04-30 10:14:03 +00:00
|
|
|
void mp_input_rm_cmd_fd(struct input_ctx *ictx, int fd)
|
|
|
|
{
|
2011-07-16 15:17:48 +00:00
|
|
|
struct input_fd *cmd_fds = ictx->cmd_fds;
|
2011-04-25 08:38:46 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ictx->num_cmd_fd; i++) {
|
|
|
|
if (cmd_fds[i].fd == fd)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (i + 1 < ictx->num_cmd_fd)
|
|
|
|
memmove(&cmd_fds[i], &cmd_fds[i + 1],
|
2011-07-16 15:17:48 +00:00
|
|
|
(ictx->num_cmd_fd - i - 1) * sizeof(struct input_fd));
|
2011-04-25 08:38:46 +00:00
|
|
|
ictx->num_cmd_fd--;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2008-04-30 08:06:55 +00:00
|
|
|
void mp_input_rm_key_fd(struct input_ctx *ictx, int fd)
|
|
|
|
{
|
2011-07-16 15:17:48 +00:00
|
|
|
struct input_fd *key_fds = ictx->key_fds;
|
2011-04-25 08:38:46 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ictx->num_key_fd; i++) {
|
|
|
|
if (key_fds[i].fd == fd)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == ictx->num_key_fd)
|
|
|
|
return;
|
|
|
|
if (key_fds[i].close_func)
|
|
|
|
key_fds[i].close_func(key_fds[i].fd);
|
|
|
|
|
|
|
|
if (i + 1 < ictx->num_key_fd)
|
|
|
|
memmove(&key_fds[i], &key_fds[i + 1],
|
2011-07-16 15:17:48 +00:00
|
|
|
(ictx->num_key_fd - i - 1) * sizeof(struct input_fd));
|
2011-04-25 08:38:46 +00:00
|
|
|
ictx->num_key_fd--;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2008-04-30 08:06:55 +00:00
|
|
|
int mp_input_add_key_fd(struct input_ctx *ictx, int fd, int select,
|
2011-07-16 15:17:48 +00:00
|
|
|
int read_func(void *ctx, int fd),
|
|
|
|
int close_func(int fd), void *ctx)
|
2008-04-29 09:55:23 +00:00
|
|
|
{
|
2011-04-25 08:38:46 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
ictx->key_fds[ictx->num_key_fd] = (struct input_fd){
|
2011-04-25 08:38:46 +00:00
|
|
|
.fd = fd,
|
|
|
|
.read_func.key = read_func,
|
|
|
|
.close_func = close_func,
|
|
|
|
.no_select = !select,
|
|
|
|
.ctx = ctx,
|
|
|
|
};
|
|
|
|
ictx->num_key_fd++;
|
|
|
|
|
|
|
|
return 1;
|
2007-08-25 04:28:14 +00:00
|
|
|
}
|
|
|
|
|
2012-10-12 07:21:26 +00:00
|
|
|
static int parse_cycle_dir(const struct m_option *opt, struct bstr name,
|
|
|
|
struct bstr param, void *dst)
|
2011-04-25 08:38:46 +00:00
|
|
|
{
|
2012-10-12 07:21:26 +00:00
|
|
|
float val;
|
|
|
|
if (bstrcmp0(param, "up") == 0) {
|
|
|
|
val = +1;
|
|
|
|
} else if (bstrcmp0(param, "down") == 0) {
|
|
|
|
val = -1;
|
|
|
|
} else {
|
|
|
|
return m_option_type_float.parse(opt, name, param, dst);
|
|
|
|
}
|
|
|
|
*(float *)dst = val;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-09-22 12:54:57 +00:00
|
|
|
static bool read_token(bstr str, bstr *out_rest, bstr *out_token)
|
2012-09-09 00:08:08 +00:00
|
|
|
{
|
2012-09-22 12:54:57 +00:00
|
|
|
bstr t = bstr_lstrip(str);
|
|
|
|
int next = bstrcspn(t, WHITESPACE "#");
|
|
|
|
// Handle comments
|
|
|
|
if (t.start[next] == '#')
|
|
|
|
t = bstr_splice(t, 0, next);
|
|
|
|
if (!t.len)
|
|
|
|
return false;
|
|
|
|
*out_token = bstr_splice(t, 0, next);
|
|
|
|
*out_rest = bstr_cut(t, next);
|
|
|
|
return true;
|
2012-09-09 00:08:08 +00:00
|
|
|
}
|
|
|
|
|
2012-09-22 12:54:57 +00:00
|
|
|
static bool eat_token(bstr *str, const char *tok)
|
2012-09-09 00:08:08 +00:00
|
|
|
{
|
2012-09-22 12:54:57 +00:00
|
|
|
bstr rest, token;
|
|
|
|
if (read_token(*str, &rest, &token) && bstrcmp0(token, tok) == 0) {
|
|
|
|
*str = rest;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2012-09-22 12:54:57 +00:00
|
|
|
static bool read_escaped_string(void *talloc_ctx, bstr *str, bstr *literal)
|
|
|
|
{
|
|
|
|
bstr t = *str;
|
|
|
|
char *new = talloc_strdup(talloc_ctx, "");
|
|
|
|
while (t.len) {
|
|
|
|
if (t.start[0] == '"')
|
|
|
|
break;
|
|
|
|
if (t.start[0] == '\\') {
|
|
|
|
t = bstr_cut(t, 1);
|
2013-02-16 21:51:10 +00:00
|
|
|
if (!mp_parse_escape(&t, &new))
|
2012-09-22 12:54:57 +00:00
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
new = talloc_strndup_append_buffer(new, t.start, 1);
|
|
|
|
t = bstr_cut(t, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int len = str->len - t.len;
|
|
|
|
*literal = new ? bstr0(new) : bstr_splice(*str, 0, len);
|
|
|
|
*str = bstr_cut(*str, len);
|
|
|
|
return true;
|
|
|
|
error:
|
|
|
|
talloc_free(new);
|
|
|
|
return false;
|
2012-09-09 00:08:08 +00:00
|
|
|
}
|
|
|
|
|
2012-10-13 19:09:42 +00:00
|
|
|
mp_cmd_t *mp_input_parse_cmd(bstr str, const char *loc)
|
2011-04-25 08:38:46 +00:00
|
|
|
{
|
|
|
|
int pausing = 0;
|
2012-09-09 00:08:08 +00:00
|
|
|
int on_osd = MP_ON_OSD_AUTO;
|
2013-05-18 10:56:22 +00:00
|
|
|
bool raw_args = false;
|
2012-09-22 12:54:57 +00:00
|
|
|
struct mp_cmd *cmd = NULL;
|
2012-10-13 19:10:20 +00:00
|
|
|
bstr start = str;
|
2012-09-22 04:33:04 +00:00
|
|
|
void *tmp = talloc_new(NULL);
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2012-09-22 12:54:57 +00:00
|
|
|
str = bstr_lstrip(str);
|
2012-09-06 05:19:41 +00:00
|
|
|
for (const struct legacy_cmd *entry = legacy_cmds; entry->old; entry++) {
|
2013-05-15 00:17:47 +00:00
|
|
|
bstr old = bstr0(entry->old);
|
|
|
|
bool silent = bstr_eatstart0(&old, "!");
|
|
|
|
if (bstrcasecmp(bstr_splice(str, 0, old.len), old) == 0) {
|
|
|
|
if (!silent) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_WARN, "Warning: command '%.*s' is "
|
|
|
|
"deprecated, replaced with '%s' at %s.\n",
|
|
|
|
BSTR_P(old), entry->new, loc);
|
|
|
|
}
|
|
|
|
bstr s = bstr_cut(str, old.len);
|
2012-09-22 12:54:57 +00:00
|
|
|
str = bstr0(talloc_asprintf(tmp, "%s%.*s", entry->new, BSTR_P(s)));
|
2012-10-13 19:10:20 +00:00
|
|
|
start = str;
|
2011-04-25 08:38:46 +00:00
|
|
|
break;
|
2012-09-06 05:19:41 +00:00
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2013-05-18 10:53:38 +00:00
|
|
|
while (1) {
|
|
|
|
if (eat_token(&str, "pausing")) {
|
|
|
|
pausing = 1;
|
|
|
|
} else if (eat_token(&str, "pausing_keep")) {
|
|
|
|
pausing = 2;
|
|
|
|
} else if (eat_token(&str, "pausing_toggle")) {
|
|
|
|
pausing = 3;
|
|
|
|
} else if (eat_token(&str, "pausing_keep_force")) {
|
|
|
|
pausing = 4;
|
|
|
|
} else if (eat_token(&str, "no-osd")) {
|
|
|
|
on_osd = MP_ON_OSD_NO;
|
|
|
|
} else if (eat_token(&str, "osd-bar")) {
|
|
|
|
on_osd = MP_ON_OSD_BAR;
|
|
|
|
} else if (eat_token(&str, "osd-msg")) {
|
|
|
|
on_osd = MP_ON_OSD_MSG;
|
|
|
|
} else if (eat_token(&str, "osd-msg-bar")) {
|
|
|
|
on_osd = MP_ON_OSD_MSG | MP_ON_OSD_BAR;
|
|
|
|
} else if (eat_token(&str, "osd-auto")) {
|
|
|
|
// default
|
2013-05-18 10:56:22 +00:00
|
|
|
} else if (eat_token(&str, "raw")) {
|
|
|
|
raw_args = true;
|
|
|
|
} else if (eat_token(&str, "expand-properties")) {
|
|
|
|
// default
|
2013-05-18 10:53:38 +00:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2012-09-09 00:08:08 +00:00
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2012-09-22 12:54:57 +00:00
|
|
|
int cmd_idx = 0;
|
|
|
|
while (mp_cmds[cmd_idx].name != NULL) {
|
|
|
|
if (eat_token(&str, mp_cmds[cmd_idx].name))
|
2011-04-25 08:38:46 +00:00
|
|
|
break;
|
2012-09-22 12:54:57 +00:00
|
|
|
cmd_idx++;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
2011-04-25 08:38:46 +00:00
|
|
|
|
2012-09-22 13:17:15 +00:00
|
|
|
if (mp_cmds[cmd_idx].name == NULL) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command '%.*s' not found.\n",
|
|
|
|
BSTR_P(str));
|
2012-09-06 05:19:41 +00:00
|
|
|
goto error;
|
2012-09-22 13:17:15 +00:00
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2012-09-06 05:19:41 +00:00
|
|
|
cmd = talloc_ptrtype(NULL, cmd);
|
2012-09-22 12:54:57 +00:00
|
|
|
*cmd = mp_cmds[cmd_idx];
|
|
|
|
cmd->pausing = pausing;
|
|
|
|
cmd->on_osd = on_osd;
|
2013-05-18 10:56:22 +00:00
|
|
|
cmd->raw_args = raw_args;
|
2011-04-25 08:38:46 +00:00
|
|
|
|
2012-09-22 12:54:57 +00:00
|
|
|
for (int i = 0; i < MP_CMD_MAX_ARGS; i++) {
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
struct mp_cmd_arg *cmdarg = &cmd->args[i];
|
|
|
|
if (!cmdarg->type.type)
|
2011-04-25 08:38:46 +00:00
|
|
|
break;
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
cmd->nargs++;
|
2012-09-22 12:54:57 +00:00
|
|
|
str = bstr_lstrip(str);
|
|
|
|
bstr arg = {0};
|
2013-05-18 11:18:01 +00:00
|
|
|
if (bstr_eatstart0(&str, "\"")) {
|
2012-09-22 12:54:57 +00:00
|
|
|
if (!read_escaped_string(tmp, &str, &arg)) {
|
2011-04-25 08:38:46 +00:00
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d "
|
2012-09-22 12:54:57 +00:00
|
|
|
"has broken string escapes.\n", cmd->name, i + 1);
|
2011-08-05 00:21:14 +00:00
|
|
|
goto error;
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
2012-09-22 12:54:57 +00:00
|
|
|
if (!bstr_eatstart0(&str, "\"")) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d is "
|
|
|
|
"unterminated.\n", cmd->name, i + 1);
|
2011-08-05 00:21:14 +00:00
|
|
|
goto error;
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
2012-09-22 12:54:57 +00:00
|
|
|
} else {
|
|
|
|
if (!read_token(str, &str, &arg))
|
|
|
|
break;
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
if (cmdarg->optional && bstrcmp0(arg, "-") == 0)
|
|
|
|
continue;
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
2012-09-22 12:54:57 +00:00
|
|
|
// Prevent option API from trying to deallocate static strings
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
cmdarg->v = ((struct mp_cmd_arg) {{0}}).v;
|
|
|
|
int r = m_option_parse(&cmdarg->type, bstr0(cmd->name), arg, &cmdarg->v);
|
2012-09-22 12:54:57 +00:00
|
|
|
if (r < 0) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d "
|
|
|
|
"can't be parsed: %s.\n", cmd->name, i + 1,
|
|
|
|
m_option_strerror(r));
|
|
|
|
goto error;
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
if (cmdarg->type.type == &m_option_type_string)
|
|
|
|
cmdarg->v.s = talloc_steal(cmd, cmdarg->v.s);
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
|
|
|
|
2012-09-22 12:54:57 +00:00
|
|
|
bstr dummy;
|
|
|
|
if (read_token(str, &dummy, &dummy)) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s has trailing unused "
|
|
|
|
"arguments: '%.*s'.\n", cmd->name, BSTR_P(str));
|
|
|
|
// Better make it fatal to make it clear something is wrong.
|
2011-08-05 00:21:14 +00:00
|
|
|
goto error;
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
|
|
|
|
2012-09-22 12:54:57 +00:00
|
|
|
int min_args = 0;
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
while (min_args < MP_CMD_MAX_ARGS && cmd->args[min_args].type.type
|
2012-09-22 12:54:57 +00:00
|
|
|
&& !cmd->args[min_args].optional)
|
|
|
|
{
|
|
|
|
min_args++;
|
|
|
|
}
|
|
|
|
if (cmd->nargs < min_args) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s requires at least %d "
|
|
|
|
"arguments, we found only %d so far.\n", cmd->name, min_args,
|
|
|
|
cmd->nargs);
|
|
|
|
goto error;
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
|
|
|
|
2012-10-13 19:10:20 +00:00
|
|
|
bstr orig = (bstr) {start.start, str.start - start.start};
|
|
|
|
cmd->original = bstrdup(cmd, bstr_strip(orig));
|
|
|
|
|
2012-09-06 05:19:41 +00:00
|
|
|
talloc_free(tmp);
|
2011-04-25 08:38:46 +00:00
|
|
|
return cmd;
|
2011-08-05 00:21:14 +00:00
|
|
|
|
2012-09-22 12:54:57 +00:00
|
|
|
error:
|
2012-10-13 19:09:42 +00:00
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command was defined at %s.\n", loc);
|
2012-09-22 12:54:57 +00:00
|
|
|
talloc_free(cmd);
|
2012-09-06 05:19:41 +00:00
|
|
|
talloc_free(tmp);
|
2011-08-05 00:21:14 +00:00
|
|
|
return NULL;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2009-06-26 20:21:38 +00:00
|
|
|
#define MP_CMD_MAX_SIZE 4096
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
static int read_cmd(struct input_fd *mp_fd, char **ret)
|
2008-04-30 06:30:51 +00:00
|
|
|
{
|
2011-04-25 08:38:46 +00:00
|
|
|
char *end;
|
|
|
|
*ret = NULL;
|
|
|
|
|
|
|
|
// Allocate the buffer if it doesn't exist
|
|
|
|
if (!mp_fd->buffer) {
|
|
|
|
mp_fd->buffer = talloc_size(NULL, MP_CMD_MAX_SIZE);
|
|
|
|
mp_fd->pos = 0;
|
|
|
|
mp_fd->size = MP_CMD_MAX_SIZE;
|
2002-04-12 10:17:24 +00:00
|
|
|
}
|
2011-04-25 08:38:46 +00:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
// Error ?
|
|
|
|
if (r < 0) {
|
|
|
|
switch (r) {
|
|
|
|
case MP_INPUT_ERROR:
|
|
|
|
case MP_INPUT_DEAD:
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Error while reading "
|
|
|
|
"command file descriptor %d: %s\n",
|
|
|
|
mp_fd->fd, strerror(errno));
|
|
|
|
case MP_INPUT_NOTHING:
|
|
|
|
return r;
|
|
|
|
case MP_INPUT_RETRY:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// EOF ?
|
|
|
|
} else if (r == 0) {
|
|
|
|
mp_fd->eof = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mp_fd->pos += r;
|
|
|
|
break;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
mp_fd->got_cmd = 0;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
int l = 0;
|
|
|
|
// Find the cmd end
|
|
|
|
mp_fd->buffer[mp_fd->pos] = '\0';
|
|
|
|
end = strchr(mp_fd->buffer, '\r');
|
|
|
|
if (end)
|
|
|
|
*end = '\n';
|
|
|
|
end = strchr(mp_fd->buffer, '\n');
|
|
|
|
// No cmd end ?
|
|
|
|
if (!end) {
|
|
|
|
// If buffer is full we must drop all until the next \n
|
|
|
|
if (mp_fd->size - mp_fd->pos <= 1) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command buffer of file "
|
|
|
|
"descriptor %d is full: dropping content.\n",
|
|
|
|
mp_fd->fd);
|
|
|
|
mp_fd->pos = 0;
|
|
|
|
mp_fd->drop = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// We already have a cmd : set the got_cmd flag
|
|
|
|
else if ((*ret)) {
|
|
|
|
mp_fd->got_cmd = 1;
|
|
|
|
break;
|
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
l = end - mp_fd->buffer;
|
2009-07-06 23:26:13 +00:00
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
// Not dropping : put the cmd in ret
|
|
|
|
if (!mp_fd->drop)
|
|
|
|
*ret = talloc_strndup(NULL, mp_fd->buffer, l);
|
|
|
|
else
|
|
|
|
mp_fd->drop = 0;
|
|
|
|
mp_fd->pos -= l + 1;
|
|
|
|
memmove(mp_fd->buffer, end + 1, mp_fd->pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*ret)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return MP_INPUT_NOTHING;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
static int default_cmd_func(int fd, char *buf, int l)
|
2008-04-30 06:30:51 +00:00
|
|
|
{
|
2011-04-25 08:38:46 +00:00
|
|
|
while (1) {
|
|
|
|
int r = read(fd, buf, l);
|
|
|
|
// Error ?
|
|
|
|
if (r < 0) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
else if (errno == EAGAIN)
|
|
|
|
return MP_INPUT_NOTHING;
|
|
|
|
return MP_INPUT_ERROR;
|
|
|
|
// EOF ?
|
|
|
|
}
|
|
|
|
return r;
|
2002-10-25 16:06:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-25 19:58:48 +00:00
|
|
|
static int read_wakeup(void *ctx, int fd)
|
|
|
|
{
|
|
|
|
char buf[100];
|
|
|
|
read(fd, buf, sizeof(buf));
|
|
|
|
return MP_INPUT_NOTHING;
|
|
|
|
}
|
|
|
|
|
2013-06-22 22:07:45 +00:00
|
|
|
static bool bind_matches_key(struct cmd_bind *bind, int n, const int *keys);
|
2012-10-13 19:10:20 +00:00
|
|
|
|
|
|
|
static void append_bind_info(char **pmsg, struct cmd_bind *bind)
|
|
|
|
{
|
|
|
|
char *msg = *pmsg;
|
|
|
|
struct mp_cmd *cmd = mp_input_parse_cmd(bstr0(bind->cmd), bind->location);
|
|
|
|
bstr stripped = cmd ? cmd->original : bstr0(bind->cmd);
|
|
|
|
msg = talloc_asprintf_append(msg, " '%.*s'", BSTR_P(stripped));
|
|
|
|
if (!cmd)
|
|
|
|
msg = talloc_asprintf_append(msg, " (invalid)");
|
|
|
|
if (strcmp(bind->owner->section, "default") != 0)
|
|
|
|
msg = talloc_asprintf_append(msg, " in section {%s}",
|
|
|
|
bind->owner->section);
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
msg = talloc_asprintf_append(msg, " in %s", bind->location);
|
2013-06-22 21:26:44 +00:00
|
|
|
if (bind->is_builtin)
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
msg = talloc_asprintf_append(msg, " (default)");
|
|
|
|
talloc_free(cmd);
|
2012-10-13 19:10:20 +00:00
|
|
|
*pmsg = msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
static mp_cmd_t *handle_test(struct input_ctx *ictx, int n, int *keys)
|
|
|
|
{
|
|
|
|
char *key_buf = get_key_combo_name(keys, n);
|
|
|
|
// "$>" to disable property substitution when invoking "show_text"
|
|
|
|
char *msg = talloc_asprintf(NULL, "$>Key %s is bound to:\n", key_buf);
|
|
|
|
talloc_free(key_buf);
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
for (struct cmd_bind_section *bs = ictx->cmd_bind_sections;
|
|
|
|
bs; bs = bs->next)
|
|
|
|
{
|
2013-06-22 22:40:35 +00:00
|
|
|
for (int i = 0; i < bs->num_binds; i++) {
|
|
|
|
if (bind_matches_key(&bs->binds[i], n, keys)) {
|
2012-10-13 19:10:20 +00:00
|
|
|
count++;
|
|
|
|
msg = talloc_asprintf_append(msg, "%d. ", count);
|
2013-06-22 22:40:35 +00:00
|
|
|
append_bind_info(&msg, &bs->binds[i]);
|
2012-10-13 19:10:20 +00:00
|
|
|
msg = talloc_asprintf_append(msg, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!count)
|
|
|
|
msg = talloc_asprintf_append(msg, "(nothing)");
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
mp_msg(MSGT_INPUT, MSGL_V, "[input] %s\n", msg);
|
|
|
|
|
2012-10-13 19:10:20 +00:00
|
|
|
mp_cmd_t *res = mp_input_parse_cmd(bstr0("show_text \"\""), "");
|
|
|
|
res->args[0].v.s = talloc_steal(res, msg);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-06-22 22:07:45 +00:00
|
|
|
static bool bind_matches_key(struct cmd_bind *bind, int num_keys, const int *keys)
|
2012-10-13 19:10:20 +00:00
|
|
|
{
|
2013-06-22 22:07:45 +00:00
|
|
|
if (bind->num_keys != num_keys)
|
|
|
|
return false;
|
|
|
|
for (int i = 0; i < num_keys; i++) {
|
|
|
|
if (bind->keys[i] != keys[i])
|
|
|
|
return false;
|
2012-10-13 19:10:20 +00:00
|
|
|
}
|
2013-06-22 22:07:45 +00:00
|
|
|
return true;
|
2012-10-13 19:10:20 +00:00
|
|
|
}
|
2002-11-14 23:41:44 +00:00
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
static struct cmd_bind_section *get_bind_section(struct input_ctx *ictx,
|
2013-06-22 21:26:44 +00:00
|
|
|
bstr section)
|
2008-04-30 05:56:45 +00:00
|
|
|
{
|
2011-07-16 15:17:48 +00:00
|
|
|
struct cmd_bind_section *bind_section = ictx->cmd_bind_sections;
|
2011-04-25 08:38:46 +00:00
|
|
|
|
2012-09-22 13:17:15 +00:00
|
|
|
if (section.len == 0)
|
|
|
|
section = bstr0("default");
|
2011-04-25 08:38:46 +00:00
|
|
|
while (bind_section) {
|
2013-06-22 21:26:44 +00:00
|
|
|
if (bstrcmp0(section, bind_section->section) == 0)
|
2011-04-25 08:38:46 +00:00
|
|
|
return bind_section;
|
|
|
|
if (bind_section->next == NULL)
|
|
|
|
break;
|
|
|
|
bind_section = bind_section->next;
|
|
|
|
}
|
|
|
|
if (bind_section) {
|
|
|
|
bind_section->next = talloc_ptrtype(ictx, bind_section->next);
|
|
|
|
bind_section = bind_section->next;
|
|
|
|
} else {
|
|
|
|
ictx->cmd_bind_sections = talloc_ptrtype(ictx, ictx->cmd_bind_sections);
|
|
|
|
bind_section = ictx->cmd_bind_sections;
|
|
|
|
}
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
*bind_section = (struct cmd_bind_section) {
|
|
|
|
.section = bstrdup0(bind_section, section),
|
|
|
|
};
|
2011-04-25 08:38:46 +00:00
|
|
|
return bind_section;
|
2007-06-07 18:06:53 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 21:26:44 +00:00
|
|
|
static struct cmd_bind *find_bind_for_key_section(struct input_ctx *ictx,
|
|
|
|
char *section,
|
2013-06-22 22:40:35 +00:00
|
|
|
int num_keys, int *keys)
|
2013-06-22 21:26:44 +00:00
|
|
|
{
|
|
|
|
struct cmd_bind_section *bs = get_bind_section(ictx, bstr0(section));
|
2013-06-22 22:40:35 +00:00
|
|
|
|
|
|
|
if (!num_keys || !bs->num_binds)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// Prefer user-defined keys over builtin bindings
|
|
|
|
for (int builtin = 0; builtin < 2; builtin++) {
|
|
|
|
for (int n = 0; n < bs->num_binds; n++) {
|
|
|
|
if (bs->binds[n].is_builtin == (bool)builtin &&
|
|
|
|
bind_matches_key(&bs->binds[n], num_keys, keys))
|
|
|
|
return &bs->binds[n];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
2013-06-22 21:26:44 +00:00
|
|
|
}
|
|
|
|
|
2013-03-30 19:07:15 +00:00
|
|
|
static struct cmd_bind *find_any_bind_for_key(struct input_ctx *ictx,
|
2013-06-19 16:19:45 +00:00
|
|
|
char *force_section,
|
2013-03-30 19:07:15 +00:00
|
|
|
int n, int *keys)
|
2008-04-30 05:56:45 +00:00
|
|
|
{
|
2013-06-22 21:26:44 +00:00
|
|
|
if (force_section)
|
|
|
|
return find_bind_for_key_section(ictx, force_section, n, keys);
|
2013-06-19 16:19:45 +00:00
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
for (int i = ictx->num_active_sections - 1; i >= 0; i--) {
|
2013-06-22 21:26:44 +00:00
|
|
|
struct active_section *s = &ictx->active_sections[i];
|
|
|
|
struct cmd_bind *bind = find_bind_for_key_section(ictx, s->name, n, keys);
|
|
|
|
if (bind) {
|
|
|
|
struct cmd_bind_section *bs = bind->owner;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
for (int i = 0; i < n; i++) {
|
2013-06-22 21:26:44 +00:00
|
|
|
if (MP_KEY_DEPENDS_ON_MOUSE_POS(keys[i]) && bs->mouse_area_set &&
|
|
|
|
!test_rect(&bs->mouse_area, ictx->mouse_vo_x, ictx->mouse_vo_y))
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
goto skip;
|
|
|
|
}
|
2013-06-22 21:26:44 +00:00
|
|
|
return bind;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
}
|
2013-06-22 21:26:44 +00:00
|
|
|
skip: ;
|
|
|
|
if (s->flags & MP_INPUT_EXCLUSIVE)
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
break;
|
2012-08-24 11:29:28 +00:00
|
|
|
}
|
2013-06-19 16:19:45 +00:00
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
return NULL;
|
2013-03-30 19:07:15 +00:00
|
|
|
}
|
|
|
|
|
2013-06-19 16:19:45 +00:00
|
|
|
static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, char *force_section,
|
|
|
|
int n, int *keys)
|
2013-03-30 19:07:15 +00:00
|
|
|
{
|
|
|
|
if (ictx->test)
|
|
|
|
return handle_test(ictx, n, keys);
|
|
|
|
|
2013-06-19 16:19:45 +00:00
|
|
|
struct cmd_bind *cmd = find_any_bind_for_key(ictx, force_section, n, keys);
|
2013-03-30 19:07:15 +00:00
|
|
|
if (cmd == NULL && n > 1) {
|
|
|
|
// Hitting two keys at once, and if there's no binding for this
|
|
|
|
// combination, the key hit last should be checked.
|
2013-06-19 16:19:45 +00:00
|
|
|
cmd = find_any_bind_for_key(ictx, force_section, 1, (int[]){keys[n - 1]});
|
2013-03-30 19:07:15 +00:00
|
|
|
}
|
2011-04-25 08:38:46 +00:00
|
|
|
|
|
|
|
if (cmd == NULL) {
|
2011-06-29 05:49:01 +00:00
|
|
|
char *key_buf = get_key_combo_name(keys, n);
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_WARN,
|
|
|
|
"No bind found for key '%s'.\n", key_buf);
|
2011-04-25 08:38:46 +00:00
|
|
|
talloc_free(key_buf);
|
|
|
|
return NULL;
|
2002-02-11 11:42:08 +00:00
|
|
|
}
|
2012-10-13 19:10:20 +00:00
|
|
|
mp_cmd_t *ret = mp_input_parse_cmd(bstr0(cmd->cmd), cmd->location);
|
2013-06-19 16:19:45 +00:00
|
|
|
if (ret) {
|
|
|
|
ret->input_section = cmd->owner->section;
|
|
|
|
} else {
|
2011-06-29 05:49:01 +00:00
|
|
|
char *key_buf = get_key_combo_name(keys, n);
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR,
|
2012-10-13 19:09:42 +00:00
|
|
|
"Invalid command for bound key '%s': '%s'\n", key_buf, cmd->cmd);
|
2011-04-25 08:38:46 +00:00
|
|
|
talloc_free(key_buf);
|
2002-02-24 21:22:12 +00:00
|
|
|
}
|
2011-04-25 08:38:46 +00:00
|
|
|
return ret;
|
2002-02-11 11:42:08 +00:00
|
|
|
}
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
static void release_down_cmd(struct input_ctx *ictx)
|
|
|
|
{
|
|
|
|
if (ictx->current_down_cmd && ictx->current_down_cmd->key_up_follows) {
|
|
|
|
ictx->current_down_cmd->key_up_follows = false;
|
|
|
|
queue_add(&ictx->key_cmd_queue, ictx->current_down_cmd, false);
|
|
|
|
} else {
|
|
|
|
talloc_free(ictx->current_down_cmd);
|
|
|
|
}
|
|
|
|
ictx->current_down_cmd = NULL;
|
|
|
|
ictx->last_key_down = 0;
|
|
|
|
ictx->ar_state = -1;
|
|
|
|
}
|
2002-11-14 23:41:44 +00:00
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
static mp_cmd_t *interpret_key(struct input_ctx *ictx, int code)
|
2007-08-25 04:28:11 +00:00
|
|
|
{
|
2011-04-25 08:38:46 +00:00
|
|
|
unsigned int j;
|
|
|
|
mp_cmd_t *ret;
|
2002-11-14 23:41:44 +00:00
|
|
|
|
2010-12-19 10:12:20 +00:00
|
|
|
/* On normal keyboards shift changes the character code of non-special
|
|
|
|
* keys, so don't count the modifier separately for those. In other words
|
|
|
|
* we want to have "a" and "A" instead of "a" and "Shift+A"; but a separate
|
|
|
|
* shift modifier is still kept for special keys like arrow keys.
|
|
|
|
*/
|
input: fix handling of MP_KEY_STATE_DOWN
VOs can use the MP_KEY_STATE_DOWN modifier to pass key up/down events to
input.c, instead of just simple key presses. This allows doing key auto-
repeat handling in input.c, if the VO doesn't want to do that.
One issue is that so far, this code has been used only for mouse events,
even though the code was originally written with keyboard keys in mind.
One difference between mouse keys and keyboard keys is that the initial
key down should not generate an input command with mouse buttons
(input.c did that), while keyboard events should (input.c didn't do
that). Likewise, releasing a key should generate input commands for
mouse buttons releases, but not for the keyboard.
Change the code so mouse buttons (recognized via the MP_NO_REPEAT_KEY
flag) follow the old hehavior, while other keys generate input commands
on key down, but not on key release.
Note that a key release event is posted either using
MP_INPUT_RELEASE_ALL, or a normal key press event after having sent a an
event with MP_KEY_STATE_DOWN. This is probably a bit confusing, and a
MP_KEY_STATE_RELEASE should be added.
Fix shift-handling with MP_KEY_STATE_DOWN as well.
2013-04-03 23:11:05 +00:00
|
|
|
int unmod = code & ~(MP_KEY_MODIFIER_MASK | MP_KEY_STATE_DOWN);
|
2012-01-14 13:09:26 +00:00
|
|
|
if (unmod >= 32 && unmod < MP_KEY_BASE)
|
2013-02-12 00:34:04 +00:00
|
|
|
code &= ~MP_KEY_MODIFIER_SHIFT;
|
2010-12-19 10:12:20 +00:00
|
|
|
|
2013-02-12 00:34:04 +00:00
|
|
|
if (code & MP_KEY_STATE_DOWN) {
|
2012-10-30 18:37:37 +00:00
|
|
|
if (ictx->num_key_down >= MP_MAX_KEY_DOWN) {
|
2011-04-25 08:38:46 +00:00
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Too many key down events "
|
|
|
|
"at the same time\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-02-12 00:34:04 +00:00
|
|
|
code &= ~MP_KEY_STATE_DOWN;
|
2011-04-25 08:38:46 +00:00
|
|
|
// Check if we don't already have this key as pushed
|
|
|
|
for (j = 0; j < ictx->num_key_down; j++) {
|
|
|
|
if (ictx->key_down[j] == code)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (j != ictx->num_key_down)
|
|
|
|
return NULL;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
release_down_cmd(ictx);
|
2011-04-25 08:38:46 +00:00
|
|
|
ictx->key_down[ictx->num_key_down] = code;
|
|
|
|
ictx->num_key_down++;
|
2013-05-25 16:31:06 +00:00
|
|
|
ictx->last_key_down = mp_time_us();
|
2011-04-25 08:38:46 +00:00
|
|
|
ictx->ar_state = 0;
|
2013-06-19 16:19:45 +00:00
|
|
|
ictx->current_down_cmd = get_cmd_from_keys(ictx, NULL, ictx->num_key_down,
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
ictx->key_down);
|
|
|
|
if (ictx->current_down_cmd && (code & MP_KEY_EMIT_ON_UP))
|
|
|
|
ictx->current_down_cmd->key_up_follows = true;
|
|
|
|
return mp_cmd_clone(ictx->current_down_cmd);
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
|
|
|
// button released or press of key with no separate down/up events
|
2008-04-30 07:21:50 +00:00
|
|
|
for (j = 0; j < ictx->num_key_down; j++) {
|
2011-04-25 08:38:46 +00:00
|
|
|
if (ictx->key_down[j] == code)
|
|
|
|
break;
|
2002-02-08 18:10:56 +00:00
|
|
|
}
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
bool doubleclick = MP_KEY_IS_MOUSE_BTN_DBL(code);
|
2011-04-25 11:12:04 +00:00
|
|
|
if (doubleclick) {
|
2013-02-12 00:34:04 +00:00
|
|
|
int btn = code - MP_MOUSE_BTN0_DBL + MP_MOUSE_BTN0;
|
2011-04-25 11:12:04 +00:00
|
|
|
if (!ictx->num_key_down
|
|
|
|
|| ictx->key_down[ictx->num_key_down - 1] != btn)
|
|
|
|
return NULL;
|
|
|
|
j = ictx->num_key_down - 1;
|
|
|
|
ictx->key_down[j] = code;
|
|
|
|
}
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
bool emit_key = ictx->last_key_down;
|
2011-04-25 08:38:46 +00:00
|
|
|
if (j == ictx->num_key_down) { // was not already down; add temporarily
|
|
|
|
if (ictx->num_key_down > MP_MAX_KEY_DOWN) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Too many key down events "
|
|
|
|
"at the same time\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ictx->key_down[ictx->num_key_down] = code;
|
|
|
|
ictx->num_key_down++;
|
input: fix handling of MP_KEY_STATE_DOWN
VOs can use the MP_KEY_STATE_DOWN modifier to pass key up/down events to
input.c, instead of just simple key presses. This allows doing key auto-
repeat handling in input.c, if the VO doesn't want to do that.
One issue is that so far, this code has been used only for mouse events,
even though the code was originally written with keyboard keys in mind.
One difference between mouse keys and keyboard keys is that the initial
key down should not generate an input command with mouse buttons
(input.c did that), while keyboard events should (input.c didn't do
that). Likewise, releasing a key should generate input commands for
mouse buttons releases, but not for the keyboard.
Change the code so mouse buttons (recognized via the MP_NO_REPEAT_KEY
flag) follow the old hehavior, while other keys generate input commands
on key down, but not on key release.
Note that a key release event is posted either using
MP_INPUT_RELEASE_ALL, or a normal key press event after having sent a an
event with MP_KEY_STATE_DOWN. This is probably a bit confusing, and a
MP_KEY_STATE_RELEASE should be added.
Fix shift-handling with MP_KEY_STATE_DOWN as well.
2013-04-03 23:11:05 +00:00
|
|
|
emit_key = true;
|
2009-07-06 23:26:13 +00:00
|
|
|
}
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
// This is a key up event, but the key up command is added by
|
|
|
|
// release_down_cmd(), not by this code.
|
2013-06-30 17:32:47 +00:00
|
|
|
if ((code & MP_KEY_EMIT_ON_UP) && ictx->current_down_cmd)
|
|
|
|
emit_key = false;
|
2011-04-25 08:38:46 +00:00
|
|
|
// Interpret only maximal point of multibutton event
|
input: fix handling of MP_KEY_STATE_DOWN
VOs can use the MP_KEY_STATE_DOWN modifier to pass key up/down events to
input.c, instead of just simple key presses. This allows doing key auto-
repeat handling in input.c, if the VO doesn't want to do that.
One issue is that so far, this code has been used only for mouse events,
even though the code was originally written with keyboard keys in mind.
One difference between mouse keys and keyboard keys is that the initial
key down should not generate an input command with mouse buttons
(input.c did that), while keyboard events should (input.c didn't do
that). Likewise, releasing a key should generate input commands for
mouse buttons releases, but not for the keyboard.
Change the code so mouse buttons (recognized via the MP_NO_REPEAT_KEY
flag) follow the old hehavior, while other keys generate input commands
on key down, but not on key release.
Note that a key release event is posted either using
MP_INPUT_RELEASE_ALL, or a normal key press event after having sent a an
event with MP_KEY_STATE_DOWN. This is probably a bit confusing, and a
MP_KEY_STATE_RELEASE should be added.
Fix shift-handling with MP_KEY_STATE_DOWN as well.
2013-04-03 23:11:05 +00:00
|
|
|
ret = NULL;
|
|
|
|
if (emit_key)
|
2013-06-19 16:19:45 +00:00
|
|
|
ret = get_cmd_from_keys(ictx, NULL, ictx->num_key_down, ictx->key_down);
|
2011-04-25 11:12:04 +00:00
|
|
|
if (doubleclick) {
|
2013-02-12 00:34:04 +00:00
|
|
|
ictx->key_down[j] = code - MP_MOUSE_BTN0_DBL + MP_MOUSE_BTN0;
|
2011-04-25 11:12:04 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2002-02-11 11:42:08 +00:00
|
|
|
// Remove the key
|
2011-04-25 08:38:46 +00:00
|
|
|
if (j + 1 < ictx->num_key_down)
|
|
|
|
memmove(&ictx->key_down[j], &ictx->key_down[j + 1],
|
|
|
|
(ictx->num_key_down - (j + 1)) * sizeof(int));
|
2008-04-30 07:21:50 +00:00
|
|
|
ictx->num_key_down--;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
release_down_cmd(ictx);
|
2007-08-25 04:28:11 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2002-02-11 11:42:08 +00:00
|
|
|
|
2010-04-25 18:47:43 +00:00
|
|
|
static mp_cmd_t *check_autorepeat(struct input_ctx *ictx)
|
2007-08-25 04:28:11 +00:00
|
|
|
{
|
2011-04-25 08:38:46 +00:00
|
|
|
// No input : autorepeat ?
|
|
|
|
if (ictx->ar_rate > 0 && ictx->ar_state >= 0 && ictx->num_key_down > 0
|
|
|
|
&& !(ictx->key_down[ictx->num_key_down - 1] & MP_NO_REPEAT_KEY)) {
|
2013-05-25 16:31:06 +00:00
|
|
|
int64_t t = mp_time_us();
|
2013-04-24 15:42:58 +00:00
|
|
|
if (ictx->last_ar + 2000000 < t)
|
|
|
|
ictx->last_ar = t;
|
2011-04-25 08:38:46 +00:00
|
|
|
// First time : wait delay
|
|
|
|
if (ictx->ar_state == 0
|
2013-02-03 16:43:47 +00:00
|
|
|
&& (t - ictx->last_key_down) >= ictx->ar_delay * 1000)
|
|
|
|
{
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
if (!ictx->current_down_cmd) {
|
2011-04-25 08:38:46 +00:00
|
|
|
ictx->ar_state = -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ictx->ar_state = 1;
|
2013-04-24 15:42:58 +00:00
|
|
|
ictx->last_ar = ictx->last_key_down + ictx->ar_delay * 1000;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
return mp_cmd_clone(ictx->current_down_cmd);
|
2011-04-25 08:38:46 +00:00
|
|
|
// Then send rate / sec event
|
|
|
|
} else if (ictx->ar_state == 1
|
|
|
|
&& (t - ictx->last_ar) >= 1000000 / ictx->ar_rate) {
|
2013-04-24 15:42:58 +00:00
|
|
|
ictx->last_ar += 1000000 / ictx->ar_rate;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
return mp_cmd_clone(ictx->current_down_cmd);
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
2002-02-03 19:13:00 +00:00
|
|
|
}
|
2011-04-25 08:38:46 +00:00
|
|
|
return NULL;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
static void add_key_cmd(struct input_ctx *ictx, struct mp_cmd *cmd)
|
|
|
|
{
|
|
|
|
struct cmd_queue *queue = &ictx->key_cmd_queue;
|
|
|
|
if (queue_count_cmds(queue) >= ictx->key_fifo_size &&
|
|
|
|
(!mp_input_is_abort_cmd(cmd->id) || queue_has_abort_cmds(queue)))
|
|
|
|
{
|
|
|
|
talloc_free(cmd);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
queue_add(queue, cmd, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Whether a command can deal with redundant key up events.
|
|
|
|
static bool key_updown_ok(enum mp_command_type cmd)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-17 01:47:50 +00:00
|
|
|
void mp_input_feed_key(struct input_ctx *ictx, int code)
|
|
|
|
{
|
|
|
|
ictx->got_new_events = true;
|
2013-05-16 21:17:46 +00:00
|
|
|
int unmod = code & ~(MP_KEY_MODIFIER_MASK | MP_KEY_STATE_DOWN);
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
if (MP_KEY_DEPENDS_ON_MOUSE_POS(unmod))
|
2013-05-25 16:31:06 +00:00
|
|
|
ictx->mouse_event_counter++;
|
2011-07-17 01:47:50 +00:00
|
|
|
if (code == MP_INPUT_RELEASE_ALL) {
|
input: fix handling of MP_KEY_STATE_DOWN
VOs can use the MP_KEY_STATE_DOWN modifier to pass key up/down events to
input.c, instead of just simple key presses. This allows doing key auto-
repeat handling in input.c, if the VO doesn't want to do that.
One issue is that so far, this code has been used only for mouse events,
even though the code was originally written with keyboard keys in mind.
One difference between mouse keys and keyboard keys is that the initial
key down should not generate an input command with mouse buttons
(input.c did that), while keyboard events should (input.c didn't do
that). Likewise, releasing a key should generate input commands for
mouse buttons releases, but not for the keyboard.
Change the code so mouse buttons (recognized via the MP_NO_REPEAT_KEY
flag) follow the old hehavior, while other keys generate input commands
on key down, but not on key release.
Note that a key release event is posted either using
MP_INPUT_RELEASE_ALL, or a normal key press event after having sent a an
event with MP_KEY_STATE_DOWN. This is probably a bit confusing, and a
MP_KEY_STATE_RELEASE should be added.
Fix shift-handling with MP_KEY_STATE_DOWN as well.
2013-04-03 23:11:05 +00:00
|
|
|
mp_msg(MSGT_INPUT, MSGL_V, "input: release all\n");
|
2011-07-17 01:47:50 +00:00
|
|
|
memset(ictx->key_down, 0, sizeof(ictx->key_down));
|
|
|
|
ictx->num_key_down = 0;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
release_down_cmd(ictx);
|
2011-07-17 01:47:50 +00:00
|
|
|
return;
|
|
|
|
}
|
input: fix handling of MP_KEY_STATE_DOWN
VOs can use the MP_KEY_STATE_DOWN modifier to pass key up/down events to
input.c, instead of just simple key presses. This allows doing key auto-
repeat handling in input.c, if the VO doesn't want to do that.
One issue is that so far, this code has been used only for mouse events,
even though the code was originally written with keyboard keys in mind.
One difference between mouse keys and keyboard keys is that the initial
key down should not generate an input command with mouse buttons
(input.c did that), while keyboard events should (input.c didn't do
that). Likewise, releasing a key should generate input commands for
mouse buttons releases, but not for the keyboard.
Change the code so mouse buttons (recognized via the MP_NO_REPEAT_KEY
flag) follow the old hehavior, while other keys generate input commands
on key down, but not on key release.
Note that a key release event is posted either using
MP_INPUT_RELEASE_ALL, or a normal key press event after having sent a an
event with MP_KEY_STATE_DOWN. This is probably a bit confusing, and a
MP_KEY_STATE_RELEASE should be added.
Fix shift-handling with MP_KEY_STATE_DOWN as well.
2013-04-03 23:11:05 +00:00
|
|
|
mp_msg(MSGT_INPUT, MSGL_V, "input: key code=%#x\n", code);
|
2011-07-17 01:47:50 +00:00
|
|
|
struct mp_cmd *cmd = interpret_key(ictx, code);
|
|
|
|
if (!cmd)
|
|
|
|
return;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
// Prevent redundant key-down events from being added to the queue. In some
|
|
|
|
// cases (like MP_CMD_SEEK commands), duplicated events might severely
|
|
|
|
// confuse the frontend.
|
|
|
|
if (cmd->key_up_follows && !key_updown_ok(cmd->id)) {
|
2012-10-14 21:45:41 +00:00
|
|
|
talloc_free(cmd);
|
2011-07-17 01:47:50 +00:00
|
|
|
return;
|
2012-10-14 21:45:41 +00:00
|
|
|
}
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
add_key_cmd(ictx, cmd);
|
|
|
|
}
|
|
|
|
|
2013-06-19 16:19:45 +00:00
|
|
|
static void trigger_mouse_leave(struct input_ctx *ictx, char *new_section)
|
|
|
|
{
|
|
|
|
if (!new_section)
|
|
|
|
new_section = "default";
|
|
|
|
|
|
|
|
char *old = ictx->mouse_section;
|
|
|
|
ictx->mouse_section = new_section;
|
|
|
|
|
|
|
|
if (old && strcmp(old, ictx->mouse_section) != 0) {
|
|
|
|
struct mp_cmd *cmd =
|
|
|
|
get_cmd_from_keys(ictx, old, 1, (int[]){MP_KEY_MOUSE_LEAVE});
|
|
|
|
if (cmd)
|
|
|
|
add_key_cmd(ictx, cmd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
void mp_input_set_mouse_pos(struct input_ctx *ictx, int x, int y)
|
|
|
|
{
|
|
|
|
ictx->mouse_event_counter++;
|
|
|
|
ictx->mouse_vo_x = x;
|
|
|
|
ictx->mouse_vo_y = y;
|
2013-06-19 16:19:45 +00:00
|
|
|
|
|
|
|
struct mp_cmd *cmd =
|
|
|
|
get_cmd_from_keys(ictx, NULL, 1, (int[]){MP_KEY_MOUSE_MOVE});
|
|
|
|
|
|
|
|
trigger_mouse_leave(ictx, cmd ? cmd->input_section : NULL);
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
if (!cmd)
|
|
|
|
return;
|
|
|
|
cmd->mouse_move = true;
|
|
|
|
cmd->mouse_x = x;
|
|
|
|
cmd->mouse_y = y;
|
|
|
|
add_key_cmd(ictx, cmd);
|
2011-07-17 01:47:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void read_cmd_fd(struct input_ctx *ictx, struct input_fd *cmd_fd)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
char *text;
|
|
|
|
while ((r = read_cmd(cmd_fd, &text)) >= 0) {
|
|
|
|
ictx->got_new_events = true;
|
2012-10-13 19:09:42 +00:00
|
|
|
struct mp_cmd *cmd = mp_input_parse_cmd(bstr0(text), "<pipe>");
|
2011-07-17 01:47:50 +00:00
|
|
|
talloc_free(text);
|
|
|
|
if (cmd)
|
|
|
|
queue_add(&ictx->control_cmd_queue, cmd, false);
|
|
|
|
if (!cmd_fd->got_cmd)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (r == MP_INPUT_ERROR)
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Error on command file descriptor %d\n",
|
|
|
|
cmd_fd->fd);
|
|
|
|
else if (r == MP_INPUT_DEAD)
|
|
|
|
cmd_fd->dead = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
if (code >= 0 || code == MP_INPUT_RELEASE_ALL) {
|
|
|
|
mp_input_feed_key(ictx, code);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (code == MP_INPUT_ERROR)
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR,
|
|
|
|
"Error on key input file descriptor %d\n", key_fd->fd);
|
|
|
|
else if (code == MP_INPUT_DEAD) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR,
|
|
|
|
"Dead key input on file descriptor %d\n", key_fd->fd);
|
|
|
|
key_fd->dead = true;
|
|
|
|
}
|
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2010-05-28 18:44:41 +00:00
|
|
|
/**
|
|
|
|
* \param time time to wait at most for an event in milliseconds
|
|
|
|
*/
|
2011-07-17 01:47:50 +00:00
|
|
|
static void read_events(struct input_ctx *ictx, int time)
|
2007-08-25 04:28:11 +00:00
|
|
|
{
|
2013-04-24 15:02:52 +00:00
|
|
|
if (ictx->num_key_down) {
|
|
|
|
time = FFMIN(time, 1000 / ictx->ar_rate);
|
|
|
|
time = FFMIN(time, ictx->ar_delay);
|
|
|
|
}
|
2013-05-16 21:17:46 +00:00
|
|
|
time = FFMAX(time, 0);
|
2011-07-17 01:47:50 +00:00
|
|
|
ictx->got_new_events = false;
|
2011-07-16 15:17:48 +00:00
|
|
|
struct input_fd *key_fds = ictx->key_fds;
|
|
|
|
struct input_fd *cmd_fds = ictx->cmd_fds;
|
2011-07-17 01:47:50 +00:00
|
|
|
for (int i = 0; i < ictx->num_key_fd; i++)
|
2011-04-25 08:38:46 +00:00
|
|
|
if (key_fds[i].dead) {
|
|
|
|
mp_input_rm_key_fd(ictx, key_fds[i].fd);
|
|
|
|
i--;
|
2011-07-17 01:47:50 +00:00
|
|
|
} 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++)
|
2011-04-25 08:38:46 +00:00
|
|
|
if (cmd_fds[i].dead || cmd_fds[i].eof) {
|
|
|
|
mp_input_rm_cmd_fd(ictx, cmd_fds[i].fd);
|
|
|
|
i--;
|
2011-07-17 01:47:50 +00:00
|
|
|
} else if (time && cmd_fds[i].no_select)
|
|
|
|
read_cmd_fd(ictx, &cmd_fds[i]);
|
|
|
|
if (ictx->got_new_events)
|
|
|
|
time = 0;
|
2007-03-21 08:24:20 +00:00
|
|
|
#ifdef HAVE_POSIX_SELECT
|
2008-04-29 09:24:02 +00:00
|
|
|
fd_set fds;
|
2007-08-25 04:28:11 +00:00
|
|
|
FD_ZERO(&fds);
|
2011-07-17 01:47:50 +00:00
|
|
|
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)
|
|
|
|
continue;
|
|
|
|
if (cmd_fds[i].fd > max_fd)
|
|
|
|
max_fd = cmd_fds[i].fd;
|
|
|
|
FD_SET(cmd_fds[i].fd, &fds);
|
|
|
|
}
|
|
|
|
struct timeval tv, *time_val;
|
2013-05-16 21:17:46 +00:00
|
|
|
tv.tv_sec = time / 1000;
|
|
|
|
tv.tv_usec = (time % 1000) * 1000;
|
|
|
|
time_val = &tv;
|
2011-07-17 01:47:50 +00:00
|
|
|
if (select(max_fd + 1, &fds, NULL, NULL, time_val) < 0) {
|
|
|
|
if (errno != EINTR)
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Select error: %s\n",
|
|
|
|
strerror(errno));
|
|
|
|
FD_ZERO(&fds);
|
2007-08-25 04:28:11 +00:00
|
|
|
}
|
|
|
|
#else
|
2013-05-16 21:17:46 +00:00
|
|
|
if (time > 0)
|
2013-05-25 17:56:52 +00:00
|
|
|
mp_sleep_us(time * 1000);
|
2003-04-04 20:56:29 +00:00
|
|
|
#endif
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2002-02-20 14:45:18 +00:00
|
|
|
|
2011-07-17 01:47:50 +00:00
|
|
|
for (int i = 0; i < ictx->num_key_fd; i++) {
|
2007-03-21 08:24:20 +00:00
|
|
|
#ifdef HAVE_POSIX_SELECT
|
2011-04-25 08:38:46 +00:00
|
|
|
if (!key_fds[i].no_select && !FD_ISSET(key_fds[i].fd, &fds))
|
|
|
|
continue;
|
2003-04-04 20:56:29 +00:00
|
|
|
#endif
|
2011-07-17 01:47:50 +00:00
|
|
|
read_key_fd(ictx, &key_fds[i]);
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
2007-08-25 04:28:11 +00:00
|
|
|
|
2011-07-17 01:47:50 +00:00
|
|
|
for (int i = 0; i < ictx->num_cmd_fd; i++) {
|
2007-03-21 08:24:20 +00:00
|
|
|
#ifdef HAVE_POSIX_SELECT
|
2011-07-17 01:47:50 +00:00
|
|
|
if (!cmd_fds[i].no_select && !FD_ISSET(cmd_fds[i].fd, &fds))
|
2011-04-25 08:38:46 +00:00
|
|
|
continue;
|
2003-04-04 20:56:29 +00:00
|
|
|
#endif
|
2011-07-17 01:47:50 +00:00
|
|
|
read_cmd_fd(ictx, &cmd_fds[i]);
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-17 01:47:50 +00:00
|
|
|
/* 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.
|
|
|
|
*/
|
2012-04-03 06:13:12 +00:00
|
|
|
static void read_all_fd_events(struct input_ctx *ictx, int time)
|
2011-07-17 01:47:50 +00:00
|
|
|
{
|
|
|
|
while (1) {
|
|
|
|
read_events(ictx, time);
|
|
|
|
if (!ictx->got_new_events)
|
|
|
|
return;
|
|
|
|
time = 0;
|
|
|
|
}
|
|
|
|
}
|
2007-08-25 04:28:11 +00:00
|
|
|
|
2012-04-03 06:13:12 +00:00
|
|
|
static void read_all_events(struct input_ctx *ictx, int time)
|
|
|
|
{
|
2013-01-23 14:47:49 +00:00
|
|
|
getch2_poll();
|
2013-06-02 15:39:05 +00:00
|
|
|
#ifdef CONFIG_COCOA
|
|
|
|
cocoa_check_events();
|
|
|
|
#endif
|
2012-04-03 06:13:12 +00:00
|
|
|
read_all_fd_events(ictx, time);
|
|
|
|
}
|
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
|
2008-04-30 10:00:59 +00:00
|
|
|
{
|
2011-07-17 01:47:50 +00:00
|
|
|
ictx->got_new_events = true;
|
|
|
|
if (!cmd)
|
2011-04-25 08:38:46 +00:00
|
|
|
return 0;
|
2013-01-15 23:35:12 +00:00
|
|
|
queue_add(&ictx->control_cmd_queue, cmd, false);
|
2011-04-25 08:38:46 +00:00
|
|
|
return 1;
|
2002-02-23 21:13:35 +00:00
|
|
|
}
|
|
|
|
|
2004-10-10 17:39:07 +00:00
|
|
|
/**
|
|
|
|
* \param peek_only when set, the returned command stays in the queue.
|
|
|
|
* Do not free the returned cmd whe you set this!
|
|
|
|
*/
|
2010-04-25 18:47:43 +00:00
|
|
|
mp_cmd_t *mp_input_get_cmd(struct input_ctx *ictx, int time, int peek_only)
|
2008-04-30 04:15:52 +00:00
|
|
|
{
|
2013-02-03 16:43:47 +00:00
|
|
|
if (async_quit_request) {
|
|
|
|
struct mp_cmd *cmd = mp_input_parse_cmd(bstr0("quit 1"), "");
|
|
|
|
queue_add(&ictx->control_cmd_queue, cmd, true);
|
|
|
|
}
|
2011-04-25 08:38:46 +00:00
|
|
|
|
2012-01-18 01:35:40 +00:00
|
|
|
if (ictx->control_cmd_queue.first || ictx->key_cmd_queue.first)
|
2011-07-17 01:47:50 +00:00
|
|
|
time = 0;
|
|
|
|
read_all_events(ictx, time);
|
|
|
|
struct cmd_queue *queue = &ictx->control_cmd_queue;
|
2012-01-18 01:35:40 +00:00
|
|
|
if (!queue->first)
|
2011-07-17 01:47:50 +00:00
|
|
|
queue = &ictx->key_cmd_queue;
|
2012-01-18 01:35:40 +00:00
|
|
|
if (!queue->first) {
|
2012-10-14 21:44:49 +00:00
|
|
|
struct mp_cmd *repeated = check_autorepeat(ictx);
|
|
|
|
if (repeated)
|
|
|
|
queue_add(queue, repeated, false);
|
|
|
|
}
|
|
|
|
struct mp_cmd *ret = queue->first;
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
2011-07-17 01:47:50 +00:00
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
if (!peek_only) {
|
2012-10-14 21:44:49 +00:00
|
|
|
queue_remove(queue, ret);
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
if (ret->mouse_move) {
|
|
|
|
ictx->mouse_x = ret->mouse_x;
|
|
|
|
ictx->mouse_y = ret->mouse_y;
|
|
|
|
}
|
|
|
|
}
|
2004-10-10 17:39:07 +00:00
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
return ret;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
void mp_input_get_mouse_pos(struct input_ctx *ictx, int *x, int *y)
|
|
|
|
{
|
|
|
|
*x = ictx->mouse_x;
|
|
|
|
*y = ictx->mouse_y;
|
|
|
|
}
|
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
void mp_cmd_free(mp_cmd_t *cmd)
|
|
|
|
{
|
2008-04-30 10:47:21 +00:00
|
|
|
talloc_free(cmd);
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2011-07-16 15:17:48 +00:00
|
|
|
mp_cmd_t *mp_cmd_clone(mp_cmd_t *cmd)
|
|
|
|
{
|
2011-04-25 08:38:46 +00:00
|
|
|
mp_cmd_t *ret;
|
|
|
|
int i;
|
2002-02-11 11:42:08 +00:00
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
if (!cmd)
|
|
|
|
return NULL;
|
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
ret = talloc_memdup(NULL, cmd, sizeof(mp_cmd_t));
|
|
|
|
ret->name = talloc_strdup(ret, cmd->name);
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
for (i = 0; i < MP_CMD_MAX_ARGS; i++) {
|
|
|
|
if (cmd->args[i].type.type == &m_option_type_string)
|
2011-04-25 08:38:46 +00:00
|
|
|
ret->args[i].v.s = talloc_strdup(ret, cmd->args[i].v.s);
|
|
|
|
}
|
2002-02-11 11:42:08 +00:00
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
return ret;
|
2002-02-11 11:42:08 +00:00
|
|
|
}
|
|
|
|
|
2010-12-19 10:12:20 +00:00
|
|
|
int mp_input_get_key_from_name(const char *name)
|
2008-04-30 06:30:51 +00:00
|
|
|
{
|
2010-12-19 10:12:20 +00:00
|
|
|
int modifiers = 0;
|
|
|
|
const char *p;
|
2011-07-07 21:41:42 +00:00
|
|
|
while ((p = strchr(name, '+'))) {
|
2011-07-16 15:17:48 +00:00
|
|
|
for (struct key_name *m = modifier_names; m->name; m++)
|
2012-07-28 21:47:42 +00:00
|
|
|
if (!bstrcasecmp(bstr0(m->name),
|
2011-07-27 05:38:12 +00:00
|
|
|
(struct bstr){(char *)name, p - name})) {
|
2010-12-19 10:12:20 +00:00
|
|
|
modifiers |= m->key;
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
if (!strcmp(name, "+"))
|
|
|
|
return '+' + modifiers;
|
|
|
|
return -1;
|
2011-04-25 08:38:46 +00:00
|
|
|
found:
|
2010-12-19 10:12:20 +00:00
|
|
|
name = p + 1;
|
|
|
|
}
|
2012-01-14 13:09:26 +00:00
|
|
|
|
2012-07-28 21:47:42 +00:00
|
|
|
struct bstr bname = bstr0(name);
|
2012-01-14 13:09:26 +00:00
|
|
|
|
|
|
|
struct bstr rest;
|
|
|
|
int code = bstr_decode_utf8(bname, &rest);
|
|
|
|
if (code >= 0 && rest.len == 0)
|
|
|
|
return code + modifiers;
|
|
|
|
|
|
|
|
if (bstr_startswith0(bname, "0x"))
|
2010-12-19 10:12:20 +00:00
|
|
|
return strtol(name, NULL, 16) + modifiers;
|
|
|
|
|
|
|
|
for (int i = 0; key_names[i].name != NULL; i++) {
|
|
|
|
if (strcasecmp(key_names[i].name, name) == 0)
|
|
|
|
return key_names[i].key + modifiers;
|
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2010-12-19 10:12:20 +00:00
|
|
|
return -1;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 22:07:45 +00:00
|
|
|
static int get_input_from_name(char *name, int *out_num_keys, int *keys)
|
2011-04-25 08:38:46 +00:00
|
|
|
{
|
|
|
|
char *end, *ptr;
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
ptr = name;
|
|
|
|
n = 0;
|
|
|
|
for (end = strchr(ptr, '-'); ptr != NULL; end = strchr(ptr, '-')) {
|
|
|
|
if (end && end[1] != '\0') {
|
|
|
|
if (end[1] == '-')
|
|
|
|
end = &end[1];
|
|
|
|
end[0] = '\0';
|
|
|
|
}
|
|
|
|
keys[n] = mp_input_get_key_from_name(ptr);
|
|
|
|
if (keys[n] < 0)
|
|
|
|
return 0;
|
|
|
|
n++;
|
|
|
|
if (end && end[1] != '\0' && n < MP_MAX_KEY_DOWN)
|
|
|
|
ptr = &end[1];
|
|
|
|
else
|
|
|
|
break;
|
2002-02-08 18:10:56 +00:00
|
|
|
}
|
2013-06-22 22:07:45 +00:00
|
|
|
*out_num_keys = n;
|
2011-04-25 08:38:46 +00:00
|
|
|
return 1;
|
2002-02-08 18:10:56 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 22:40:35 +00:00
|
|
|
static void bind_dealloc(struct cmd_bind *bind)
|
|
|
|
{
|
|
|
|
talloc_free(bind->cmd);
|
|
|
|
talloc_free(bind->location);
|
|
|
|
}
|
|
|
|
|
2012-09-22 13:17:15 +00:00
|
|
|
static void bind_keys(struct input_ctx *ictx, bool builtin, bstr section,
|
2013-06-22 22:07:45 +00:00
|
|
|
const int *keys, int num_keys, bstr command,
|
2012-10-13 19:09:42 +00:00
|
|
|
const char *loc)
|
2008-04-30 05:56:45 +00:00
|
|
|
{
|
2013-06-22 22:40:35 +00:00
|
|
|
struct cmd_bind_section *bs = get_bind_section(ictx, section);
|
2011-07-16 15:17:48 +00:00
|
|
|
struct cmd_bind *bind = NULL;
|
2011-04-25 08:38:46 +00:00
|
|
|
|
2013-06-22 22:07:45 +00:00
|
|
|
assert(num_keys <= MP_MAX_KEY_DOWN);
|
|
|
|
|
2013-06-22 22:40:35 +00:00
|
|
|
for (int n = 0; n < bs->num_binds; n++) {
|
|
|
|
struct cmd_bind *b = &bs->binds[n];
|
|
|
|
if (bind_matches_key(b, num_keys, keys) && b->is_builtin == builtin) {
|
|
|
|
bind = b;
|
|
|
|
break;
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bind) {
|
2013-06-22 22:40:35 +00:00
|
|
|
struct cmd_bind empty = {{0}};
|
|
|
|
MP_TARRAY_APPEND(bs, bs->binds, bs->num_binds, empty);
|
|
|
|
bind = &bs->binds[bs->num_binds - 1];
|
2002-02-24 16:31:27 +00:00
|
|
|
}
|
2013-06-22 22:40:35 +00:00
|
|
|
|
|
|
|
bind_dealloc(bind);
|
|
|
|
|
|
|
|
*bind = (struct cmd_bind) {
|
|
|
|
.cmd = bstrdup0(bs->binds, command),
|
|
|
|
.location = talloc_strdup(bs->binds, loc),
|
|
|
|
.owner = bs,
|
|
|
|
.is_builtin = builtin,
|
|
|
|
.num_keys = num_keys,
|
|
|
|
};
|
2013-06-22 22:07:45 +00:00
|
|
|
memcpy(bind->keys, keys, num_keys * sizeof(bind->keys[0]));
|
2002-02-24 16:31:27 +00:00
|
|
|
}
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
// restrict_section: every entry is forced to this section name
|
|
|
|
// if NULL, load normally and allow any sections
|
2012-10-13 19:09:42 +00:00
|
|
|
static int parse_config(struct input_ctx *ictx, bool builtin, bstr data,
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
const char *location, const char *restrict_section)
|
2008-04-30 05:56:45 +00:00
|
|
|
{
|
2013-06-22 22:07:45 +00:00
|
|
|
int n_binds = 0;
|
2012-10-13 19:09:42 +00:00
|
|
|
int line_no = 0;
|
|
|
|
char *cur_loc = NULL;
|
2011-07-20 01:41:51 +00:00
|
|
|
|
2012-08-01 19:50:24 +00:00
|
|
|
while (data.len) {
|
2012-10-13 19:09:42 +00:00
|
|
|
line_no++;
|
|
|
|
if (cur_loc)
|
|
|
|
talloc_free(cur_loc);
|
|
|
|
cur_loc = talloc_asprintf(NULL, "%s:%d", location, line_no);
|
|
|
|
|
2012-08-01 19:50:24 +00:00
|
|
|
bstr line = bstr_strip_linebreaks(bstr_getline(data, &data));
|
|
|
|
line = bstr_lstrip(line);
|
|
|
|
if (line.len == 0 || bstr_startswith0(line, "#"))
|
2011-04-25 08:38:46 +00:00
|
|
|
continue;
|
2011-07-20 01:41:51 +00:00
|
|
|
struct bstr command;
|
|
|
|
// Find the key name starting a line
|
2012-08-01 21:41:21 +00:00
|
|
|
struct bstr keyname = bstr_split(line, WHITESPACE, &command);
|
2011-07-20 01:41:51 +00:00
|
|
|
command = bstr_strip(command);
|
|
|
|
if (command.len == 0) {
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR,
|
2012-10-13 19:09:42 +00:00
|
|
|
"Unfinished key binding: %.*s at %s\n", BSTR_P(line),
|
|
|
|
cur_loc);
|
2011-07-20 01:41:51 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
char *name = bstrdup0(NULL, keyname);
|
2013-06-22 22:07:45 +00:00
|
|
|
int keys[MP_MAX_KEY_DOWN];
|
|
|
|
int num_keys = 0;
|
|
|
|
if (!get_input_from_name(name, &num_keys, keys)) {
|
2011-07-20 01:41:51 +00:00
|
|
|
talloc_free(name);
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR,
|
2012-10-13 19:09:42 +00:00
|
|
|
"Unknown key '%.*s' at %s\n", BSTR_P(keyname), cur_loc);
|
2011-04-25 08:38:46 +00:00
|
|
|
continue;
|
2010-12-19 10:12:20 +00:00
|
|
|
}
|
2011-07-20 01:41:51 +00:00
|
|
|
talloc_free(name);
|
2012-09-22 13:17:15 +00:00
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
bstr section = bstr0(restrict_section);
|
|
|
|
if (!section.len) {
|
|
|
|
if (bstr_startswith0(command, "{")) {
|
|
|
|
int p = bstrchr(command, '}');
|
|
|
|
if (p != -1) {
|
|
|
|
section = bstr_strip(bstr_splice(command, 1, p));
|
|
|
|
command = bstr_lstrip(bstr_cut(command, p + 1));
|
|
|
|
}
|
2012-09-22 13:17:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-22 22:07:45 +00:00
|
|
|
bind_keys(ictx, builtin, section, keys, num_keys, command, cur_loc);
|
2011-07-20 01:41:51 +00:00
|
|
|
n_binds++;
|
2012-09-22 04:33:04 +00:00
|
|
|
|
|
|
|
// Print warnings if invalid commands are encountered.
|
2012-10-13 19:09:42 +00:00
|
|
|
talloc_free(mp_input_parse_cmd(command, cur_loc));
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
2012-08-01 19:50:24 +00:00
|
|
|
|
2012-10-13 19:09:42 +00:00
|
|
|
talloc_free(cur_loc);
|
|
|
|
|
2012-08-01 19:50:24 +00:00
|
|
|
return n_binds;
|
|
|
|
}
|
|
|
|
|
2013-02-08 22:52:06 +00:00
|
|
|
static int parse_config_file(struct input_ctx *ictx, char *file, bool warn)
|
2012-08-01 19:50:24 +00:00
|
|
|
{
|
2012-11-15 11:40:39 +00:00
|
|
|
if (!mp_path_exists(file)) {
|
2013-02-08 22:52:06 +00:00
|
|
|
mp_msg(MSGT_INPUT, warn ? MSGL_ERR : MSGL_V,
|
|
|
|
"Input config file %s not found.\n", file);
|
2012-11-15 11:40:39 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2012-08-01 19:50:24 +00:00
|
|
|
stream_t *s = open_stream(file, NULL, NULL);
|
|
|
|
if (!s) {
|
2013-02-08 22:52:06 +00:00
|
|
|
mp_msg(MSGT_INPUT, MSGL_ERR, "Can't open input config file %s.\n", file);
|
2012-08-01 19:50:24 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2013-06-11 10:16:42 +00:00
|
|
|
bstr res = stream_read_complete(s, NULL, 1000000);
|
2012-08-01 19:50:24 +00:00
|
|
|
free_stream(s);
|
|
|
|
mp_msg(MSGT_INPUT, MSGL_V, "Parsing input config file %s\n", file);
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
int n_binds = parse_config(ictx, false, res, file, NULL);
|
2012-08-01 19:50:24 +00:00
|
|
|
talloc_free(res.start);
|
|
|
|
mp_msg(MSGT_INPUT, MSGL_V, "Input config file %s parsed: %d binds\n",
|
|
|
|
file, n_binds);
|
|
|
|
return 1;
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 21:26:44 +00:00
|
|
|
// If name is NULL, return "default".
|
|
|
|
// Return a statically allocated name of the section (i.e. return value never
|
|
|
|
// gets deallocated).
|
|
|
|
static char *normalize_section(struct input_ctx *ictx, char *name)
|
|
|
|
{
|
|
|
|
return get_bind_section(ictx, bstr0(name))->section;
|
|
|
|
}
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
void mp_input_disable_section(struct input_ctx *ictx, char *name)
|
|
|
|
{
|
2013-06-22 21:26:44 +00:00
|
|
|
name = normalize_section(ictx, name);
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
|
|
|
|
// Remove old section, or make sure it's on top if re-enabled
|
|
|
|
for (int i = ictx->num_active_sections - 1; i >= 0; i--) {
|
|
|
|
struct active_section *as = &ictx->active_sections[i];
|
|
|
|
if (strcmp(as->name, name) == 0) {
|
|
|
|
for (int x = i; i < ictx->num_active_sections - 1; i++)
|
|
|
|
ictx->active_sections[x] = ictx->active_sections[x + 1];
|
|
|
|
ictx->num_active_sections--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void mp_input_enable_section(struct input_ctx *ictx, char *name, int flags)
|
|
|
|
{
|
2013-06-22 21:26:44 +00:00
|
|
|
name = normalize_section(ictx, name);
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
|
|
|
|
mp_input_disable_section(ictx, name);
|
|
|
|
|
|
|
|
if (ictx->num_active_sections < MAX_ACTIVE_SECTIONS) {
|
|
|
|
ictx->active_sections[ictx->num_active_sections++] =
|
|
|
|
(struct active_section) {name, flags};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void mp_input_disable_all_sections(struct input_ctx *ictx)
|
|
|
|
{
|
|
|
|
ictx->num_active_sections = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mp_input_set_section_mouse_area(struct input_ctx *ictx, char *name,
|
|
|
|
int x0, int y0, int x1, int y1)
|
2008-04-30 05:56:45 +00:00
|
|
|
{
|
2013-06-22 21:26:44 +00:00
|
|
|
struct cmd_bind_section *s = get_bind_section(ictx, bstr0(name));
|
|
|
|
s->mouse_area = (struct mp_rect){x0, y0, x1, y1};
|
|
|
|
s->mouse_area_set = x0 != x1 && y0 != y1;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool mp_input_test_mouse_active(struct input_ctx *ictx, int x, int y)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < ictx->num_active_sections; i++) {
|
|
|
|
char *name = ictx->active_sections[i].name;
|
2013-06-22 21:26:44 +00:00
|
|
|
struct cmd_bind_section *s = get_bind_section(ictx, bstr0(name));
|
|
|
|
if (s->mouse_area_set && test_rect(&s->mouse_area, x, y))
|
|
|
|
return true;
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mp_input_test_dragging(struct input_ctx *ictx, int x, int y)
|
|
|
|
{
|
|
|
|
return mp_input_test_mouse_active(ictx, x, y);
|
2007-06-07 18:06:53 +00:00
|
|
|
}
|
|
|
|
|
2013-06-22 22:40:35 +00:00
|
|
|
// builtin: if true, remove all builtin binds, else remove all user binds
|
|
|
|
static void remove_binds(struct cmd_bind_section *bs, bool builtin)
|
2013-06-22 21:26:44 +00:00
|
|
|
{
|
2013-06-22 22:40:35 +00:00
|
|
|
for (int n = bs->num_binds - 1; n >= 0; n--) {
|
|
|
|
if (bs->binds[n].is_builtin == builtin) {
|
|
|
|
bind_dealloc(&bs->binds[n]);
|
|
|
|
assert(bs->num_binds >= 1);
|
|
|
|
bs->binds[n] = bs->binds[bs->num_binds - 1];
|
|
|
|
bs->num_binds--;
|
2013-06-22 21:26:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
void mp_input_define_section(struct input_ctx *ictx, char *name, char *location,
|
|
|
|
char *contents, bool builtin)
|
2008-04-30 05:56:45 +00:00
|
|
|
{
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
if (!name || !name[0])
|
|
|
|
return; // parse_config() changes semantics with restrict_section==empty
|
|
|
|
if (contents) {
|
|
|
|
parse_config(ictx, builtin, bstr0(contents), location, name);
|
|
|
|
} else {
|
|
|
|
// Disable:
|
|
|
|
mp_input_disable_section(ictx, name);
|
|
|
|
// Delete:
|
2013-06-22 22:40:35 +00:00
|
|
|
struct cmd_bind_section *bs = get_bind_section(ictx, bstr0(name));
|
|
|
|
remove_binds(bs, builtin);
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
}
|
2007-06-07 18:06:53 +00:00
|
|
|
}
|
|
|
|
|
2013-02-08 22:52:06 +00:00
|
|
|
struct input_ctx *mp_input_init(struct input_conf *input_conf,
|
|
|
|
bool load_default_conf)
|
2008-04-30 04:15:52 +00:00
|
|
|
{
|
|
|
|
struct input_ctx *ictx = talloc_ptrtype(NULL, ictx);
|
|
|
|
*ictx = (struct input_ctx){
|
2011-07-17 01:47:50 +00:00
|
|
|
.key_fifo_size = input_conf->key_fifo_size,
|
2008-04-30 04:15:52 +00:00
|
|
|
.ar_state = -1,
|
2008-04-30 15:57:02 +00:00
|
|
|
.ar_delay = input_conf->ar_delay,
|
|
|
|
.ar_rate = input_conf->ar_rate,
|
2009-03-31 23:26:34 +00:00
|
|
|
.default_bindings = input_conf->default_bindings,
|
2012-10-13 19:10:20 +00:00
|
|
|
.test = input_conf->test,
|
2012-03-25 19:58:48 +00:00
|
|
|
.wakeup_pipe = {-1, -1},
|
2008-04-30 04:15:52 +00:00
|
|
|
};
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
mp_input_enable_section(ictx, NULL, 0);
|
2012-08-01 20:45:35 +00:00
|
|
|
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
parse_config(ictx, true, bstr0(builtin_input_conf), "<builtin>", NULL);
|
2008-04-30 04:15:52 +00:00
|
|
|
|
2012-03-25 19:58:48 +00:00
|
|
|
#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
|
|
|
|
|
2013-02-08 22:52:06 +00:00
|
|
|
bool config_ok = false;
|
|
|
|
if (input_conf->config_file)
|
|
|
|
config_ok = parse_config_file(ictx, input_conf->config_file, true);
|
|
|
|
if (!config_ok && load_default_conf) {
|
2011-04-25 08:38:46 +00:00
|
|
|
// Try global conf dir
|
2013-02-08 22:52:06 +00:00
|
|
|
char *file = mp_find_config_file("input.conf");
|
|
|
|
config_ok = file && parse_config_file(ictx, file, false);
|
|
|
|
talloc_free(file);
|
|
|
|
}
|
|
|
|
if (!config_ok) {
|
|
|
|
mp_msg(MSGT_INPUT, MSGL_V, "Falling back on default (hardcoded) "
|
|
|
|
"input config\n");
|
2004-08-03 12:21:14 +00:00
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
|
2008-08-07 08:58:07 +00:00
|
|
|
#ifdef CONFIG_JOYSTICK
|
2011-04-25 08:38:46 +00:00
|
|
|
if (input_conf->use_joystick) {
|
|
|
|
int fd = mp_input_joystick_init(input_conf->js_dev);
|
|
|
|
if (fd < 0)
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Can't init input joystick\n");
|
|
|
|
else
|
|
|
|
mp_input_add_key_fd(ictx, fd, 1, mp_input_joystick_read,
|
2011-07-16 15:17:48 +00:00
|
|
|
close, NULL);
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
2002-01-30 12:46:03 +00:00
|
|
|
#endif
|
|
|
|
|
2008-08-07 08:58:07 +00:00
|
|
|
#ifdef CONFIG_LIRC
|
2011-04-25 08:38:46 +00:00
|
|
|
if (input_conf->use_lirc) {
|
|
|
|
int fd = mp_input_lirc_init();
|
|
|
|
if (fd > 0)
|
|
|
|
mp_input_add_cmd_fd(ictx, fd, 0, mp_input_lirc_read,
|
|
|
|
mp_input_lirc_close);
|
|
|
|
}
|
2002-01-31 09:39:11 +00:00
|
|
|
#endif
|
|
|
|
|
2008-08-07 08:58:07 +00:00
|
|
|
#ifdef CONFIG_LIRCC
|
2011-04-25 08:38:46 +00:00
|
|
|
if (input_conf->use_lircc) {
|
2012-10-11 00:04:08 +00:00
|
|
|
int fd = lircc_init("mpv", NULL);
|
2011-04-25 08:38:46 +00:00
|
|
|
if (fd >= 0)
|
2011-07-16 15:17:48 +00:00
|
|
|
mp_input_add_cmd_fd(ictx, fd, 1, NULL, lircc_cleanup);
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
2003-05-30 18:23:55 +00:00
|
|
|
#endif
|
|
|
|
|
2013-06-02 22:52:40 +00:00
|
|
|
#ifdef CONFIG_COCOA
|
|
|
|
if (input_conf->use_ar) {
|
2013-06-04 20:12:23 +00:00
|
|
|
cocoa_init_apple_remote();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (input_conf->use_media_keys) {
|
|
|
|
cocoa_init_media_keys();
|
2013-06-02 22:52:40 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
if (input_conf->in_file) {
|
2012-02-03 07:05:11 +00:00
|
|
|
int mode = O_RDONLY;
|
|
|
|
#ifndef __MINGW32__
|
2011-04-25 08:38:46 +00:00
|
|
|
// Use RDWR for FIFOs to ensure they stay open over multiple accesses.
|
2012-02-03 07:05:11 +00:00
|
|
|
// Note that on Windows due to how the API works, using RDONLY should
|
|
|
|
// be ok.
|
|
|
|
struct stat st;
|
2011-04-25 08:38:46 +00:00
|
|
|
if (stat(input_conf->in_file, &st) == 0 && S_ISFIFO(st.st_mode))
|
2012-02-03 07:05:11 +00:00
|
|
|
mode = O_RDWR;
|
|
|
|
mode |= O_NONBLOCK;
|
|
|
|
#endif
|
2011-04-25 08:38:46 +00:00
|
|
|
int in_file_fd = open(input_conf->in_file, mode);
|
|
|
|
if (in_file_fd >= 0)
|
2011-07-16 15:17:48 +00:00
|
|
|
mp_input_add_cmd_fd(ictx, in_file_fd, 1, NULL, close);
|
2011-04-25 08:38:46 +00:00
|
|
|
else
|
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Can't open %s: %s\n",
|
|
|
|
input_conf->in_file, strerror(errno));
|
|
|
|
}
|
2012-04-03 06:13:12 +00:00
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
return ictx;
|
2002-01-31 09:39:11 +00:00
|
|
|
}
|
|
|
|
|
2013-02-03 16:43:47 +00:00
|
|
|
static void clear_queue(struct cmd_queue *queue)
|
|
|
|
{
|
|
|
|
while (queue->first) {
|
|
|
|
struct mp_cmd *item = queue->first;
|
|
|
|
queue_remove(queue, item);
|
|
|
|
talloc_free(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-02 22:52:40 +00:00
|
|
|
void mp_input_uninit(struct input_ctx *ictx, struct input_conf *input_conf)
|
2008-04-30 04:15:52 +00:00
|
|
|
{
|
2008-04-30 06:14:06 +00:00
|
|
|
if (!ictx)
|
|
|
|
return;
|
|
|
|
|
2013-06-02 22:52:40 +00:00
|
|
|
#ifdef CONFIG_COCOA
|
|
|
|
if (input_conf->use_ar) {
|
2013-06-04 20:12:23 +00:00
|
|
|
cocoa_uninit_apple_remote();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (input_conf->use_media_keys) {
|
|
|
|
cocoa_uninit_media_keys();
|
2013-06-02 22:52:40 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-03-25 19:58:48 +00:00
|
|
|
for (int i = 0; i < ictx->num_key_fd; i++) {
|
2011-04-25 08:38:46 +00:00
|
|
|
if (ictx->key_fds[i].close_func)
|
|
|
|
ictx->key_fds[i].close_func(ictx->key_fds[i].fd);
|
|
|
|
}
|
2012-03-25 19:58:48 +00:00
|
|
|
for (int i = 0; i < ictx->num_cmd_fd; i++) {
|
2011-04-25 08:38:46 +00:00
|
|
|
if (ictx->cmd_fds[i].close_func)
|
|
|
|
ictx->cmd_fds[i].close_func(ictx->cmd_fds[i].fd);
|
|
|
|
}
|
2013-02-03 16:43:47 +00:00
|
|
|
for (int i = 0; i < 2; i++) {
|
2012-03-25 19:58:48 +00:00
|
|
|
if (ictx->wakeup_pipe[i] != -1)
|
|
|
|
close(ictx->wakeup_pipe[i]);
|
2013-02-03 16:43:47 +00:00
|
|
|
}
|
|
|
|
clear_queue(&ictx->key_cmd_queue);
|
|
|
|
clear_queue(&ictx->control_cmd_queue);
|
input: handle mouse movement differently
Before this commit, mouse movement events emitted a special command
("set_mouse_pos"), which was specially handled in command.c. This was
once special-cased to the dvdnav and menu code, and did nothing after
libmenu and dvdnav were removed.
Change it so that mouse movement triggers a pseudo-key ("MOUSE_MOVE"),
which then can be bound to an arbitrary command. The mouse position is
now managed in input.c. A command which actually needs the mouse
position can use either mp_input_get_mouse_pos() or mp_get_osd_mouse_pos()
to query it. The former returns raw window-space coordinates, while the
latter returns coordinates transformed to OSD- space. (Both are the same
for most VOs, except vo_xv and vo_x11, which can't render OSD in
window-space. These require extra code for mapping mouse position.)
As of this commit, there is still nothing that uses mouse movement, so
MOUSE_MOVE is mapped to "ignore" to silence warnings when moving the
mouse (much like MOUSE_BTN0).
Extend the concept of input sections. Allow multiple sections to be
active at once, and organize them as stack. Bindings from the top of
the stack are preferred to lower ones.
Each section has a mouse input section associated, inside which mouse
events are associated with the bindings. If the mouse pointer is
outside of a section's mouse area, mouse events will be dispatched to
an input section lower on the stack of active sections. This is intended
for scripting, which is to be added later. Two scripts could occupy
different areas of the screen without conflicting with each other. (If
it turns out that this mechanism is useless, we'll just remove it
again.)
2013-04-26 00:13:30 +00:00
|
|
|
talloc_free(ictx->current_down_cmd);
|
2011-04-25 08:38:46 +00:00
|
|
|
talloc_free(ictx);
|
2002-01-30 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2011-04-25 08:38:46 +00:00
|
|
|
void mp_input_register_options(m_config_t *cfg)
|
|
|
|
{
|
|
|
|
m_config_register_options(cfg, mp_input_opts);
|
2002-02-11 11:42:08 +00:00
|
|
|
}
|
|
|
|
|
2012-05-07 20:16:20 +00:00
|
|
|
static int print_key_list(m_option_t *cfg, char *optname, char *optparam)
|
2008-04-30 06:30:51 +00:00
|
|
|
{
|
2011-04-25 08:38:46 +00:00
|
|
|
int i;
|
|
|
|
printf("\n");
|
|
|
|
for (i = 0; key_names[i].name != NULL; i++)
|
|
|
|
printf("%s\n", key_names[i].name);
|
2012-05-07 20:16:20 +00:00
|
|
|
return M_OPT_EXIT;
|
2002-03-20 13:30:57 +00:00
|
|
|
}
|
|
|
|
|
2012-05-07 20:16:20 +00:00
|
|
|
static int print_cmd_list(m_option_t *cfg, char *optname, char *optparam)
|
2008-04-30 06:30:51 +00:00
|
|
|
{
|
2011-04-25 08:38:46 +00:00
|
|
|
const mp_cmd_t *cmd;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; (cmd = &mp_cmds[i])->name != NULL; i++) {
|
|
|
|
printf("%-20.20s", cmd->name);
|
commands: add choice type to input commands
Allow using the choice type (as it used for command line) for arguments
of input commands. Change the magic integer arguments of some commands
(like seek) to use choices instead. The old numeric values are still
allowed (but only those which made sense before, not arbitrary
integers).
In order to do this, remove the input.c specific types (like
MP_CMD_ARG_INT) completely and specify commands using the m_option
types.
Also, add the special choice "-" to some arguments. It's supposed to
signify the default value, so arguments can be easily skipped. Maybe the
choice option should recognize this and not change the previous value,
but we'll leave this for later.
For now, leave compatibility integer values for all new choice
arguments, e.g. "0" maps to 0. We could let the choice option type do
this automatically, but we don't, because we want user input values and
internal mplayer values decoupled in general. The compatibility options
will be removed one day, too.
Also, remove optional args for strings - would require either annoying
additional code, or copying strings twice. It's not used, so remove it.
2012-09-24 19:57:43 +00:00
|
|
|
for (j = 0; j < MP_CMD_MAX_ARGS && cmd->args[j].type.type; j++) {
|
|
|
|
const char *type = cmd->args[j].type.type->name;
|
2012-03-21 00:23:35 +00:00
|
|
|
if (cmd->args[j].optional)
|
2011-04-25 08:38:46 +00:00
|
|
|
printf(" [%s]", type);
|
|
|
|
else
|
|
|
|
printf(" %s", type);
|
|
|
|
}
|
|
|
|
printf("\n");
|
2002-03-20 13:30:57 +00:00
|
|
|
}
|
2012-05-07 20:16:20 +00:00
|
|
|
return M_OPT_EXIT;
|
2002-03-20 13:30:57 +00:00
|
|
|
}
|
2002-10-23 14:46:20 +00:00
|
|
|
|
2012-03-25 19:58:48 +00:00
|
|
|
void mp_input_wakeup(struct input_ctx *ictx)
|
|
|
|
{
|
|
|
|
if (ictx->wakeup_pipe[1] >= 0)
|
|
|
|
write(ictx->wakeup_pipe[1], &(char){0}, 1);
|
|
|
|
}
|
|
|
|
|
2010-05-28 18:44:41 +00:00
|
|
|
/**
|
|
|
|
* \param time time to wait for an interruption in milliseconds
|
|
|
|
*/
|
2008-04-30 04:15:52 +00:00
|
|
|
int mp_input_check_interrupt(struct input_ctx *ictx, int time)
|
|
|
|
{
|
2011-07-17 01:47:50 +00:00
|
|
|
for (int i = 0; ; i++) {
|
2012-01-18 01:35:40 +00:00
|
|
|
if (async_quit_request || queue_has_abort_cmds(&ictx->key_cmd_queue) ||
|
|
|
|
queue_has_abort_cmds(&ictx->control_cmd_queue)) {
|
2011-07-17 01:47:50 +00:00
|
|
|
mp_tmsg(MSGT_INPUT, MSGL_WARN, "Received command to move to "
|
|
|
|
"another file. Aborting current processing.\n");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (i)
|
|
|
|
return false;
|
|
|
|
read_all_events(ictx, time);
|
2011-04-25 08:38:46 +00:00
|
|
|
}
|
2002-10-23 14:46:20 +00:00
|
|
|
}
|
2013-05-16 21:17:46 +00:00
|
|
|
|
2013-05-25 16:31:06 +00:00
|
|
|
unsigned int mp_input_get_mouse_event_counter(struct input_ctx *ictx)
|
2013-05-16 21:17:46 +00:00
|
|
|
{
|
2013-06-19 16:45:02 +00:00
|
|
|
// Make the frontend always display the mouse cursor (as long as it's not
|
|
|
|
// forced invisible) if mouse input is desired.
|
|
|
|
if (mp_input_test_mouse_active(ictx, ictx->mouse_x, ictx->mouse_y))
|
|
|
|
ictx->mouse_event_counter++;
|
2013-05-25 16:31:06 +00:00
|
|
|
return ictx->mouse_event_counter;
|
2013-05-16 21:17:46 +00:00
|
|
|
}
|