diff options
Diffstat (limited to 'command.c')
-rw-r--r-- | command.c | 1739 |
1 files changed, 571 insertions, 1168 deletions
@@ -39,7 +39,6 @@ #include "m_option.h" #include "m_property.h" #include "m_config.h" -#include "metadata.h" #include "libmpcodecs/vf.h" #include "libmpcodecs/vd.h" #include "mp_osd.h" @@ -72,6 +71,16 @@ #include "mp_fifo.h" #include "libavutil/avstring.h" +static char *format_bitrate(int rate) +{ + return talloc_asprintf(NULL, "%d kbps", rate * 8 / 1000); +} + +static char *format_delay(double time) +{ + return talloc_asprintf(NULL, "%d ms", ROUND(time * 1000)); +} + static void rescale_input_coordinates(struct MPContext *mpctx, int ix, int iy, double *dx, double *dy) { @@ -105,110 +114,29 @@ static void rescale_input_coordinates(struct MPContext *mpctx, int ix, int iy, vo->dheight, vo_fs); } -static void choice_get_min_max(const struct m_option *opt, int *min, int *max) -{ - assert(opt->type == &m_option_type_choice); - *min = INT_MAX; - *max = INT_MIN; - for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) { - *min = FFMIN(*min, alt->value); - *max = FFMAX(*max, alt->value); - } - if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) { - *min = FFMIN(*min, opt->min); - *max = FFMAX(*max, opt->max); - } -} - -static void check_choice(int dir, int val, bool *found, int *best, int choice) -{ - if ((dir == -1 && (!(*found) || choice > (*best)) && choice < val) || - (dir == +1 && (!(*found) || choice < (*best)) && choice > val)) - { - *found = true; - *best = choice; - } -} - -static int step_choice(const struct m_option *opt, int val, int add, bool wrap) -{ - assert(opt->type == &m_option_type_choice); - int dir = add > 0 ? +1 : -1; - bool found = false; - int best = 0; // init. value unused - - if (add == 0) - return val; - - if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) { - int newval = val + add; - if (val >= opt->min && val <= opt->max && - newval >= opt->min && newval <= opt->max) - { - found = true; - best = newval; - } else { - check_choice(dir, val, &found, &best, opt->min); - check_choice(dir, val, &found, &best, opt->max); - } - } - - for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) - check_choice(dir, val, &found, &best, alt->value); - - if (!found) { - int min, max; - choice_get_min_max(opt, &min, &max); - best = (dir == -1) ^ wrap ? min : max; - } - - return best; -} - +// Property-option bridge. static int mp_property_generic_option(struct m_option *prop, int action, void *arg, MPContext *mpctx) { char *optname = prop->priv; - const struct m_option *opt = m_config_get_option(mpctx->mconfig, - bstr0(optname)); - void *valptr = m_option_get_ptr(opt, &mpctx->opts); + struct m_config_option *opt = m_config_get_co(mpctx->mconfig, + bstr0(optname)); + void *valptr = opt->data; switch (action) { case M_PROPERTY_GET_TYPE: - *(const struct m_option **)arg = opt; + *(struct m_option *)arg = *(opt->opt); return M_PROPERTY_OK; case M_PROPERTY_GET: - m_option_copy(opt, arg, valptr); + m_option_copy(opt->opt, arg, valptr); return M_PROPERTY_OK; case M_PROPERTY_SET: - m_option_copy(opt, valptr, arg); + m_option_copy(opt->opt, valptr, arg); return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - if (opt->type == &m_option_type_choice) { - int add = arg ? (*(int *)arg) : +1; - int v = *(int *) valptr; - *(int *) valptr = step_choice(opt, v, add, true); - return M_PROPERTY_OK; - } - break; } return M_PROPERTY_NOT_IMPLEMENTED; } -/// OSD level (RW) -static int mp_property_osdlevel(m_option_t *prop, int action, void *arg, - MPContext *mpctx) -{ - return m_property_choice(prop, action, arg, &mpctx->opts.osd_level); -} - -/// Loop (RW) -static int mp_property_loop(m_option_t *prop, int action, void *arg, - MPContext *mpctx) -{ - return mp_property_generic_option(prop, action, arg, mpctx); -} - /// Playback speed (RW) static int mp_property_playback_speed(m_option_t *prop, int action, void *arg, MPContext *mpctx) @@ -216,43 +144,45 @@ static int mp_property_playback_speed(m_option_t *prop, int action, struct MPOpts *opts = &mpctx->opts; double orig_speed = opts->playback_speed; switch (action) { - case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; + case M_PROPERTY_SET: { opts->playback_speed = *(float *) arg; - goto set; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - opts->playback_speed += (arg ? *(float *) arg : 0.1) * - (action == M_PROPERTY_STEP_DOWN ? -1 : 1); - set: - M_PROPERTY_CLAMP(prop, opts->playback_speed); // Adjust time until next frame flip for nosound mode mpctx->time_frame *= orig_speed / opts->playback_speed; reinit_audio_chain(mpctx); return M_PROPERTY_OK; } - return m_property_float_range(prop, action, arg, &opts->playback_speed); + case M_PROPERTY_PRINT: + *(char **)arg = talloc_asprintf(NULL, "x %6.2f", orig_speed); + return M_PROPERTY_OK; + } + return mp_property_generic_option(prop, action, arg, mpctx); } /// filename with path (RO) static int mp_property_path(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - return m_property_string_ro(prop, action, arg, mpctx->filename); + if (action == M_PROPERTY_GET) { + *(char **)arg = talloc_strdup(NULL, mpctx->filename); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } /// filename without path (RO) static int mp_property_filename(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - char *f; if (!mpctx->filename) return M_PROPERTY_UNAVAILABLE; - f = (char *)mp_basename(mpctx->filename); - if (!*f) - f = mpctx->filename; - return m_property_string_ro(prop, action, arg, f); + if (action == M_PROPERTY_GET) { + char *f = (char *)mp_basename(mpctx->filename); + if (!*f) + f = mpctx->filename; + *(char **)arg = talloc_strdup(NULL, f); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Demuxer name (RO) @@ -262,7 +192,11 @@ static int mp_property_demuxer(m_option_t *prop, int action, void *arg, struct demuxer *demuxer = mpctx->master_demuxer; if (!demuxer) return M_PROPERTY_UNAVAILABLE; - return m_property_string_ro(prop, action, arg, (char *)demuxer->desc->name); + if (action == M_PROPERTY_GET) { + *(char **)arg = talloc_strdup(NULL, demuxer->desc->name); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Position in the stream (RW) @@ -272,15 +206,12 @@ static int mp_property_stream_pos(m_option_t *prop, int action, void *arg, struct stream *stream = mpctx->stream; if (!stream) return M_PROPERTY_UNAVAILABLE; - if (!arg) - return M_PROPERTY_ERROR; switch (action) { case M_PROPERTY_GET: - *(off_t *) arg = stream_tell(stream); + *(int64_t *) arg = stream_tell(stream); return M_PROPERTY_OK; case M_PROPERTY_SET: - M_PROPERTY_CLAMP(prop, *(off_t *) arg); - stream_seek(stream, *(off_t *) arg); + stream_seek(stream, *(int64_t *) arg); return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; @@ -295,7 +226,7 @@ static int mp_property_stream_start(m_option_t *prop, int action, return M_PROPERTY_UNAVAILABLE; switch (action) { case M_PROPERTY_GET: - *(off_t *) arg = stream->start_pos; + *(int64_t *) arg = stream->start_pos; return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; @@ -310,7 +241,7 @@ static int mp_property_stream_end(m_option_t *prop, int action, void *arg, return M_PROPERTY_UNAVAILABLE; switch (action) { case M_PROPERTY_GET: - *(off_t *) arg = stream->end_pos; + *(int64_t *) arg = stream->end_pos; return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; @@ -325,7 +256,7 @@ static int mp_property_stream_length(m_option_t *prop, int action, return M_PROPERTY_UNAVAILABLE; switch (action) { case M_PROPERTY_GET: - *(off_t *) arg = stream->end_pos - stream->start_pos; + *(int64_t *) arg = stream->end_pos - stream->start_pos; return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; @@ -342,7 +273,7 @@ static int mp_property_stream_time_pos(m_option_t *prop, int action, if (pts == MP_NOPTS_VALUE) return M_PROPERTY_UNAVAILABLE; - return m_property_time_ro(prop, action, arg, pts); + return m_property_double_ro(prop, action, arg, pts); } @@ -355,38 +286,26 @@ static int mp_property_length(m_option_t *prop, int action, void *arg, if (!(int) (len = get_time_length(mpctx))) return M_PROPERTY_UNAVAILABLE; - return m_property_time_ro(prop, action, arg, len); + return m_property_double_ro(prop, action, arg, len); } /// Current position in percent (RW) static int mp_property_percent_pos(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - int pos; - if (!mpctx->num_sources) return M_PROPERTY_UNAVAILABLE; switch (action) { - case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop, *(int *)arg); - pos = *(int *)arg; - break; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - pos = get_percent_pos(mpctx); - pos += (arg ? *(int *)arg : 10) * - (action == M_PROPERTY_STEP_UP ? 1 : -1); - M_PROPERTY_CLAMP(prop, pos); - break; - default: - return m_property_int_ro(prop, action, arg, get_percent_pos(mpctx)); + case M_PROPERTY_SET: ; + int pos = *(int *)arg; + queue_seek(mpctx, MPSEEK_FACTOR, pos / 100.0, 0); + return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = get_percent_pos(mpctx); + return M_PROPERTY_OK; } - - queue_seek(mpctx, MPSEEK_FACTOR, pos / 100.0, 0); - return M_PROPERTY_OK; + return M_PROPERTY_NOT_IMPLEMENTED; } /// Current position in seconds (RW) @@ -398,83 +317,48 @@ static int mp_property_time_pos(m_option_t *prop, int action, switch (action) { case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop, *(double *)arg); queue_seek(mpctx, MPSEEK_ABSOLUTE, *(double *)arg, 0); return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - queue_seek(mpctx, MPSEEK_RELATIVE, (arg ? *(double *)arg : 10.0) * - (action == M_PROPERTY_STEP_UP ? 1.0 : -1.0), 0); + case M_PROPERTY_GET: + *(double *)arg = get_current_time(mpctx); return M_PROPERTY_OK; } - return m_property_time_ro(prop, action, arg, get_current_time(mpctx)); + return M_PROPERTY_NOT_IMPLEMENTED; } /// Current chapter (RW) static int mp_property_chapter(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - struct MPOpts *opts = &mpctx->opts; - int step_all; - char *chapter_name = NULL; - int chapter = get_current_chapter(mpctx); if (chapter < -1) return M_PROPERTY_UNAVAILABLE; switch (action) { case M_PROPERTY_GET: - if (!arg) - return M_PROPERTY_ERROR; *(int *) arg = chapter; return M_PROPERTY_OK; case M_PROPERTY_PRINT: { - if (!arg) - return M_PROPERTY_ERROR; - chapter_name = chapter_display_name(mpctx, chapter); + char *chapter_name = chapter_display_name(mpctx, chapter); if (!chapter_name) return M_PROPERTY_UNAVAILABLE; *(char **) arg = chapter_name; return M_PROPERTY_OK; } - case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop, *(int *)arg); - step_all = *(int *)arg - chapter; - chapter += step_all; - break; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: { - step_all = (arg && *(int *)arg != 0 ? *(int *)arg : 1) - * (action == M_PROPERTY_STEP_UP ? 1 : -1); + case M_PROPERTY_SET: ; + int step_all = *(int *)arg - chapter; chapter += step_all; - if (chapter < 0) - chapter = 0; - break; - } - default: - return M_PROPERTY_NOT_IMPLEMENTED; + double next_pts = 0; + queue_seek(mpctx, MPSEEK_NONE, 0, 0); + chapter = seek_chapter(mpctx, chapter, &next_pts); + if (chapter >= 0) { + if (next_pts > -1.0) + queue_seek(mpctx, MPSEEK_ABSOLUTE, next_pts, 0); + } else if (step_all > 0) + mpctx->stop_play = PT_NEXT_ENTRY; + return M_PROPERTY_OK; } - - double next_pts = 0; - queue_seek(mpctx, MPSEEK_NONE, 0, 0); - chapter = seek_chapter(mpctx, chapter, &next_pts); - if (chapter >= 0) { - if (next_pts > -1.0) - queue_seek(mpctx, MPSEEK_ABSOLUTE, next_pts, 0); - chapter_name = chapter_display_name(mpctx, chapter); - set_osd_tmsg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, - "Chapter: %s", chapter_name); - } else if (step_all > 0) - mpctx->stop_play = PT_NEXT_ENTRY; - else - set_osd_tmsg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, - "Chapter: (%d) %s", 0, mp_gtext("unknown")); - talloc_free(chapter_name); - return M_PROPERTY_OK; + return M_PROPERTY_NOT_IMPLEMENTED; } static int mp_property_edition(m_option_t *prop, int action, void *arg, @@ -491,35 +375,29 @@ static int mp_property_edition(m_option_t *prop, int action, void *arg, switch (action) { case M_PROPERTY_GET: - case M_PROPERTY_PRINT: - return m_property_int_ro(prop, action, arg, edition); - case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop, *(int *)arg); + *(int *)arg = edition; + return M_PROPERTY_OK; + case M_PROPERTY_SET: { edition = *(int *)arg; - break; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: { - edition += arg ? *(int *)arg : (action == M_PROPERTY_STEP_UP ? 1 : -1); - if (edition < 0) - edition = demuxer->num_editions - 1; - if (edition >= demuxer->num_editions) - edition = 0; - break; + if (edition != demuxer->edition) { + opts->edition_id = edition; + mpctx->stop_play = PT_RESTART; + } + return M_PROPERTY_OK; } - default: - return M_PROPERTY_NOT_IMPLEMENTED; + case M_PROPERTY_GET_TYPE: { + struct m_option opt = { + .name = prop->name, + .type = CONF_TYPE_INT, + .flags = CONF_RANGE, + .min = 0, + .max = demuxer->num_editions - 1, + }; + *(struct m_option *)arg = opt; + return M_PROPERTY_OK; } - - if (edition != demuxer->edition) { - opts->edition_id = edition; - mpctx->stop_play = PT_RESTART; - set_osd_tmsg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, - "Playing edition %d of %d.", edition + 1, - demuxer->num_editions); } - return M_PROPERTY_OK; + return M_PROPERTY_NOT_IMPLEMENTED; } /// Number of titles in file @@ -559,7 +437,6 @@ static int mp_property_editions(m_option_t *prop, int action, void *arg, static int mp_property_angle(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - struct MPOpts *opts = &mpctx->opts; struct demuxer *demuxer = mpctx->master_demuxer; int angle = -1; int angles; @@ -574,54 +451,26 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg, switch (action) { case M_PROPERTY_GET: - if (!arg) - return M_PROPERTY_ERROR; *(int *) arg = angle; return M_PROPERTY_OK; case M_PROPERTY_PRINT: { - if (!arg) - return M_PROPERTY_ERROR; *(char **) arg = talloc_asprintf(NULL, "%d/%d", angle, angles); return M_PROPERTY_OK; } case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - angle = *(int *)arg; - M_PROPERTY_CLAMP(prop, angle); - break; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: { - int step = 0; - if (arg) - step = *(int *)arg; - if (!step) - step = 1; - step *= (action == M_PROPERTY_STEP_UP ? 1 : -1); - angle += step; - if (angle < 1) //cycle - angle = angles; - else if (angle > angles) - angle = 1; - break; - } - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } - angle = demuxer_set_angle(demuxer, angle); - if (angle >= 0) { - struct sh_video *sh_video = demuxer->video->sh; - if (sh_video) - resync_video_stream(sh_video); - - struct sh_audio *sh_audio = demuxer->audio->sh; - if (sh_audio) - resync_audio_stream(sh_audio); + angle = demuxer_set_angle(demuxer, *(int *)arg); + if (angle >= 0) { + struct sh_video *sh_video = demuxer->video->sh; + if (sh_video) + resync_video_stream(sh_video); + + struct sh_audio *sh_audio = demuxer->audio->sh; + if (sh_audio) + resync_audio_stream(sh_audio); + } + return M_PROPERTY_OK; } - - set_osd_tmsg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, - "Angle: %d/%d", angle, angles); - return M_PROPERTY_OK; + return M_PROPERTY_NOT_IMPLEMENTED; } /// Demuxer meta data @@ -632,38 +481,33 @@ static int mp_property_metadata(m_option_t *prop, int action, void *arg, if (!demuxer) return M_PROPERTY_UNAVAILABLE; - m_property_action_t *ka; - char *meta; static const m_option_t key_type = { "metadata", NULL, CONF_TYPE_STRING, 0, 0, 0, NULL }; switch (action) { - case M_PROPERTY_GET: - if (!arg) - return M_PROPERTY_ERROR; - *(char ***)arg = demuxer->info; + case M_PROPERTY_GET: { + char **slist = NULL; + m_option_copy(prop, &slist, &demuxer->info); + *(char ***)arg = slist; return M_PROPERTY_OK; - case M_PROPERTY_KEY_ACTION: - if (!arg) - return M_PROPERTY_ERROR; - ka = arg; - if (!(meta = demux_info_get(demuxer, ka->key))) + } + case M_PROPERTY_KEY_ACTION: { + struct m_property_action_arg *ka = arg; + char *meta = demux_info_get(demuxer, ka->key); + if (!meta) return M_PROPERTY_UNKNOWN; switch (ka->action) { case M_PROPERTY_GET: - if (!ka->arg) - return M_PROPERTY_ERROR; - *(char **)ka->arg = meta; + *(char **)ka->arg = talloc_strdup(NULL, meta); return M_PROPERTY_OK; case M_PROPERTY_GET_TYPE: - if (!ka->arg) - return M_PROPERTY_ERROR; - *(const m_option_t **)ka->arg = &key_type; + *(struct m_option *)ka->arg = key_type; return M_PROPERTY_OK; } } + } return M_PROPERTY_NOT_IMPLEMENTED; } @@ -674,21 +518,17 @@ static int mp_property_pause(m_option_t *prop, int action, void *arg, switch (action) { case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - if (mpctx->paused == (bool) * (int *)arg) - return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - if (mpctx->paused) { - unpause_player(mpctx); - } else { + if (*(int *)arg) { pause_player(mpctx); + } else { + unpause_player(mpctx); } return M_PROPERTY_OK; - default: - return m_property_flag(prop, action, arg, &mpctx->paused); + case M_PROPERTY_GET: + *(int *)arg = mpctx->paused; + return M_PROPERTY_OK; } + return M_PROPERTY_NOT_IMPLEMENTED; } @@ -702,44 +542,19 @@ static int mp_property_volume(m_option_t *prop, int action, void *arg, switch (action) { case M_PROPERTY_GET: - if (!arg) - return M_PROPERTY_ERROR; mixer_getbothvolume(&mpctx->mixer, arg); return M_PROPERTY_OK; - case M_PROPERTY_PRINT: { - float vol; - if (!arg) - return M_PROPERTY_ERROR; - mixer_getbothvolume(&mpctx->mixer, &vol); - return m_property_float_range(prop, action, arg, &vol); - } - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - case M_PROPERTY_SET: - break; - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } - - switch (action) { case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop, *(float *) arg); mixer_setvolume(&mpctx->mixer, *(float *) arg, *(float *) arg); return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - if (arg && *(float *) arg <= 0) + case M_PROPERTY_SWITCH: { + struct m_property_switch_arg *sarg = arg; + if (sarg->inc <= 0) mixer_decvolume(&mpctx->mixer); else mixer_incvolume(&mpctx->mixer); return M_PROPERTY_OK; - case M_PROPERTY_STEP_DOWN: - if (arg && *(float *) arg <= 0) - mixer_incvolume(&mpctx->mixer); - else - mixer_decvolume(&mpctx->mixer); - return M_PROPERTY_OK; + } } return M_PROPERTY_NOT_IMPLEMENTED; } @@ -754,18 +569,13 @@ static int mp_property_mute(m_option_t *prop, int action, void *arg, switch (action) { case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; mixer_setmute(&mpctx->mixer, *(int *) arg); return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - mixer_setmute(&mpctx->mixer, !mixer_getmute(&mpctx->mixer)); + case M_PROPERTY_GET: + *(int *)arg = mixer_getmute(&mpctx->mixer); return M_PROPERTY_OK; - default: - return m_property_flag_ro(prop, action, arg, - mixer_getmute(&mpctx->mixer)); } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Audio delay (RW) @@ -775,21 +585,14 @@ static int mp_property_audio_delay(m_option_t *prop, int action, if (!(mpctx->sh_audio && mpctx->sh_video)) return M_PROPERTY_UNAVAILABLE; switch (action) { + case M_PROPERTY_PRINT: + *(char **)arg = format_delay(audio_delay); + return M_PROPERTY_OK; case M_PROPERTY_SET: - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: { - int ret; - float delay = audio_delay; - ret = m_property_delay(prop, action, arg, &audio_delay); - if (ret != M_PROPERTY_OK) - return ret; - if (mpctx->sh_audio) - mpctx->delay -= audio_delay - delay; - } + mpctx->delay -= audio_delay - *(float *)arg; return M_PROPERTY_OK; - default: - return m_property_delay(prop, action, arg, &audio_delay); } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Audio codec tag (RO) @@ -807,8 +610,11 @@ static int mp_property_audio_codec(m_option_t *prop, int action, { if (!mpctx->sh_audio || !mpctx->sh_audio->codec) return M_PROPERTY_UNAVAILABLE; - return m_property_string_ro(prop, action, arg, - mpctx->sh_audio->codec->name); + if (action == M_PROPERTY_GET) { + *(char **)arg = talloc_strdup(NULL, mpctx->sh_audio->codec->name); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Audio bitrate (RO) @@ -817,7 +623,15 @@ static int mp_property_audio_bitrate(m_option_t *prop, int action, { if (!mpctx->sh_audio) return M_PROPERTY_UNAVAILABLE; - return m_property_bitrate(prop, action, arg, mpctx->sh_audio->i_bps); + switch (action) { + case M_PROPERTY_PRINT: + *(char **)arg = format_bitrate(mpctx->sh_audio->i_bps); + return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = mpctx->sh_audio->i_bps; + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Samplerate (RO) @@ -828,13 +642,14 @@ static int mp_property_samplerate(m_option_t *prop, int action, void *arg, return M_PROPERTY_UNAVAILABLE; switch (action) { case M_PROPERTY_PRINT: - if (!arg) - return M_PROPERTY_ERROR; *(char **)arg = talloc_asprintf(NULL, "%d kHz", mpctx->sh_audio->samplerate / 1000); return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = mpctx->sh_audio->samplerate; + return M_PROPERTY_OK; } - return m_property_int_ro(prop, action, arg, mpctx->sh_audio->samplerate); + return M_PROPERTY_NOT_IMPLEMENTED; } /// Number of channels (RO) @@ -845,8 +660,6 @@ static int mp_property_channels(m_option_t *prop, int action, void *arg, return M_PROPERTY_UNAVAILABLE; switch (action) { case M_PROPERTY_PRINT: - if (!arg) - return M_PROPERTY_ERROR; switch (mpctx->sh_audio->channels) { case 1: *(char **) arg = talloc_strdup(NULL, "mono"); @@ -859,8 +672,11 @@ static int mp_property_channels(m_option_t *prop, int action, void *arg, mpctx->sh_audio->channels); } return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = mpctx->sh_audio->channels; + return M_PROPERTY_OK; } - return m_property_int_ro(prop, action, arg, mpctx->sh_audio->channels); + return M_PROPERTY_NOT_IMPLEMENTED; } /// Balance (RW) @@ -871,14 +687,10 @@ static int mp_property_balance(m_option_t *prop, int action, void *arg, switch (action) { case M_PROPERTY_GET: - if (!arg) - return M_PROPERTY_ERROR; mixer_getbalance(&mpctx->mixer, arg); return M_PROPERTY_OK; case M_PROPERTY_PRINT: { char **str = arg; - if (!arg) - return M_PROPERTY_ERROR; mixer_getbalance(&mpctx->mixer, &bal); if (bal == 0.f) *str = talloc_strdup(NULL, "center"); @@ -893,18 +705,7 @@ static int mp_property_balance(m_option_t *prop, int action, void *arg, } return M_PROPERTY_OK; } - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - mixer_getbalance(&mpctx->mixer, &bal); - bal += (arg ? *(float *)arg : .1f) * - (action == M_PROPERTY_STEP_UP ? 1.f : -1.f); - M_PROPERTY_CLAMP(prop, bal); - mixer_setbalance(&mpctx->mixer, bal); - return M_PROPERTY_OK; case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop, *(float *)arg); mixer_setbalance(&mpctx->mixer, *(float *)arg); return M_PROPERTY_OK; } @@ -943,14 +744,9 @@ static int property_switch_track(m_option_t *prop, int action, void *arg, switch (action) { case M_PROPERTY_GET: - if (!arg) - return M_PROPERTY_ERROR; *(int *) arg = track ? track->user_tid : -1; return M_PROPERTY_OK; case M_PROPERTY_PRINT: - if (!arg) - return M_PROPERTY_ERROR; - if (!track) *(char **) arg = talloc_strdup(NULL, mp_gtext("disabled")); else { @@ -967,18 +763,15 @@ static int property_switch_track(m_option_t *prop, int action, void *arg, } return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - case M_PROPERTY_SET: { - int i = (arg ? *((int *) arg) : +1) * - (action == M_PROPERTY_STEP_DOWN ? -1 : +1); - if (action == M_PROPERTY_SET && arg) - track = mp_track_by_tid(mpctx, type, i); - else - track = track_next(mpctx, type, i > 0 ? +1 : -1, track); - mp_switch_track(mpctx, type, track); + case M_PROPERTY_SWITCH: { + struct m_property_switch_arg *sarg = arg; + mp_switch_track(mpctx, type, + track_next(mpctx, type, sarg->inc >= 0 ? +1 : -1, track)); return M_PROPERTY_OK; } + case M_PROPERTY_SET: + mp_switch_track(mpctx, type, mp_track_by_tid(mpctx, type, *(int *)arg)); + return M_PROPERTY_OK; default: return M_PROPERTY_NOT_IMPLEMENTED; } @@ -998,6 +791,18 @@ static int mp_property_video(m_option_t *prop, int action, void *arg, return property_switch_track(prop, action, arg, mpctx, STREAM_VIDEO); } +static struct track *find_track_by_demuxer_id(MPContext *mpctx, + enum stream_type type, + int demuxer_id) +{ + for (int n = 0; n < mpctx->num_tracks; n++) { + struct track *track = mpctx->tracks[n]; + if (track->type == type && track->demuxer_id == demuxer_id) + return track; + } + return NULL; +} + static int mp_property_program(m_option_t *prop, int action, void *arg, MPContext *mpctx) { @@ -1008,7 +813,7 @@ static int mp_property_program(m_option_t *prop, int action, void *arg, return M_PROPERTY_UNAVAILABLE; switch (action) { - case M_PROPERTY_STEP_UP: + case M_PROPERTY_SWITCH: case M_PROPERTY_SET: if (action == M_PROPERTY_SET && arg) prog.progid = *((int *) arg); @@ -1023,13 +828,13 @@ static int mp_property_program(m_option_t *prop, int action, void *arg, "Selected program contains no audio or video streams!\n"); return M_PROPERTY_ERROR; } - mp_property_do("switch_audio", M_PROPERTY_SET, &prog.aid, mpctx); - mp_property_do("switch_video", M_PROPERTY_SET, &prog.vid, mpctx); + mp_switch_track(mpctx, STREAM_AUDIO, + find_track_by_demuxer_id(mpctx, STREAM_AUDIO, prog.aid)); + mp_switch_track(mpctx, STREAM_VIDEO, + find_track_by_demuxer_id(mpctx, STREAM_VIDEO, prog.vid)); return M_PROPERTY_OK; - - default: - return M_PROPERTY_NOT_IMPLEMENTED; } + return M_PROPERTY_NOT_IMPLEMENTED; } @@ -1041,68 +846,42 @@ static int mp_property_fullscreen(m_option_t *prop, int action, void *arg, if (!mpctx->video_out) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop, *(int *) arg); + if (action == M_PROPERTY_SET) { if (vo_fs == !!*(int *) arg) return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: if (mpctx->video_out->config_ok) vo_control(mpctx->video_out, VOCTRL_FULLSCREEN, 0); mpctx->opts.fullscreen = vo_fs; return M_PROPERTY_OK; - default: - return m_property_flag(prop, action, arg, &vo_fs); } + return mp_property_generic_option(prop, action, arg, mpctx); } static int mp_property_deinterlace(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - int deinterlace; vf_instance_t *vf; if (!mpctx->sh_video || !mpctx->sh_video->vfilter) return M_PROPERTY_UNAVAILABLE; vf = mpctx->sh_video->vfilter; switch (action) { case M_PROPERTY_GET: - if (!arg) - return M_PROPERTY_ERROR; vf->control(vf, VFCTRL_GET_DEINTERLACE, arg); return M_PROPERTY_OK; case M_PROPERTY_SET: - if (!arg) - return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop, *(int *) arg); vf->control(vf, VFCTRL_SET_DEINTERLACE, arg); return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - vf->control(vf, VFCTRL_GET_DEINTERLACE, &deinterlace); - deinterlace = !deinterlace; - vf->control(vf, VFCTRL_SET_DEINTERLACE, &deinterlace); - return M_PROPERTY_OK; } - int value = 0; - vf->control(vf, VFCTRL_GET_DEINTERLACE, &value); - return m_property_flag_ro(prop, action, arg, value); + return M_PROPERTY_NOT_IMPLEMENTED; } static int colormatrix_property_helper(m_option_t *prop, int action, void *arg, MPContext *mpctx) { int r = mp_property_generic_option(prop, action, arg, mpctx); - // testing for an actual change is too much effort - switch (action) { - case M_PROPERTY_SET: - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: + if (action == M_PROPERTY_SET) { if (mpctx->sh_video) set_video_colorspace(mpctx->sh_video); - break; } return r; } @@ -1110,81 +889,75 @@ static int colormatrix_property_helper(m_option_t *prop, int action, static int mp_property_colormatrix(m_option_t *prop, int action, void *arg, MPContext *mpctx) { + if (action != M_PROPERTY_PRINT) + return colormatrix_property_helper(prop, action, arg, mpctx); + struct MPOpts *opts = &mpctx->opts; - switch (action) { - case M_PROPERTY_PRINT: - if (!arg) - return M_PROPERTY_ERROR; - struct mp_csp_details actual = { .format = -1 }; - char *req_csp = mp_csp_names[opts->requested_colorspace]; - char *real_csp = NULL; - if (mpctx->sh_video) { - struct vf_instance *vf = mpctx->sh_video->vfilter; - if (vf |