diff --git a/options/options.c b/options/options.c index 64b264323e..078f606289 100644 --- a/options/options.c +++ b/options/options.c @@ -212,6 +212,22 @@ const struct m_sub_options vo_sub_opts = { }, }; +#undef OPT_BASE_STRUCT +#define OPT_BASE_STRUCT struct dvd_opts + +const struct m_sub_options dvd_conf = { + .opts = (const struct m_option[]){ + OPT_STRING("dvd-device", device, M_OPT_FILE), + OPT_INT("dvd-speed", speed, 0), + OPT_INTRANGE("dvd-angle", angle, 0, 1, 99), + {0} + }, + .size = sizeof(struct dvd_opts), + .defaults = &(const struct dvd_opts){ + .angle = 1, + }, +}; + #undef OPT_BASE_STRUCT #define OPT_BASE_STRUCT struct MPOpts @@ -275,9 +291,7 @@ const m_option_t mp_opts[] = { OPT_SUBSTRUCT("", stream_cache, stream_cache_conf, 0), #if HAVE_DVDREAD || HAVE_DVDNAV - OPT_STRING("dvd-device", dvd_device, M_OPT_FILE), - OPT_INT("dvd-speed", dvd_speed, 0), - OPT_INTRANGE("dvd-angle", dvd_angle, 0, 1, 99), + OPT_SUBSTRUCT("", dvd_opts, dvd_conf, 0), #endif /* HAVE_DVDREAD */ OPT_INTPAIR("chapter", chapterrange, 0), OPT_CHOICE_OR_INT("edition", edition_id, 0, 0, 8190, @@ -855,8 +869,6 @@ const struct MPOpts mp_default_opts = { .index_mode = 1, - .dvd_angle = 1, - .mf_fps = 1.0, .display_tags = (char **)(const char*[]){ diff --git a/options/options.h b/options/options.h index 34ca1f320e..b0871a1d8f 100644 --- a/options/options.h +++ b/options/options.h @@ -290,10 +290,6 @@ typedef struct MPOpts { struct stream_lavf_params *stream_lavf_opts; char *cdrom_device; - int dvd_title; - int dvd_angle; - int dvd_speed; - char *dvd_device; char *bluray_device; double mf_fps; @@ -318,11 +314,19 @@ typedef struct MPOpts { char *input_file; struct gl_video_opts *gl_video_opts; + struct dvd_opts *dvd_opts; } MPOpts; +struct dvd_opts { + int angle; + int speed; + char *device; +}; + extern const m_option_t mp_opts[]; extern const struct MPOpts mp_default_opts; extern const struct m_sub_options vo_sub_opts; extern const struct m_sub_options stream_cache_conf; +extern const struct m_sub_options dvd_conf; #endif diff --git a/player/configfiles.c b/player/configfiles.c index ed53e5882c..3d056d15d3 100644 --- a/player/configfiles.c +++ b/player/configfiles.c @@ -180,8 +180,8 @@ static char *mp_get_playback_resume_config_filename(struct MPContext *mpctx, realpath = mp_path_join(tmp, cwd, fname); } } - if (bstr_startswith0(bfname, "dvd://") && opts->dvd_device) - realpath = talloc_asprintf(tmp, "%s - %s", realpath, opts->dvd_device); + if (bstr_startswith0(bfname, "dvd://") && opts->dvd_opts->device) + realpath = talloc_asprintf(tmp, "%s - %s", realpath, opts->dvd_opts->device); if ((bstr_startswith0(bfname, "br://") || bstr_startswith0(bfname, "bd://") || bstr_startswith0(bfname, "bluray://")) && opts->bluray_device) realpath = talloc_asprintf(tmp, "%s - %s", realpath, opts->bluray_device); diff --git a/stream/stream.c b/stream/stream.c index 69772f335a..ed7697e9c6 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -207,18 +207,22 @@ static bstr split_next(bstr *s, char end, const char *delim) // Parse the stream URL, syntax: // proto:// [@][:][/] -// (the proto:// part is already removed from s->path) +// (the proto:// part is assumed to be already removed from s) // This code originates from times when http code used this, but now it's // just relict from other stream implementations reusing this code. +void mp_parse_legacy_url(bstr s, bstr c[4]) +{ + c[0] = split_next(&s, '@', "@:/"); + c[1] = split_next(&s, 0, ":/"); + c[2] = bstr_eatstart0(&s, ":") ? split_next(&s, 0, "/") : (bstr){0}; + c[3] = bstr_eatstart0(&s, "/") ? s : (bstr){0}; +} + static bool parse_url(struct stream *st, struct m_config *config) { - bstr s = bstr0(st->path); - const char *f_names[4] = {"username", "hostname", "port", "filename"}; bstr f[4]; - f[0] = split_next(&s, '@', "@:/"); - f[1] = split_next(&s, 0, ":/"); - f[2] = bstr_eatstart0(&s, ":") ? split_next(&s, 0, "/") : (bstr){0}; - f[3] = bstr_eatstart0(&s, "/") ? s : (bstr){0}; + mp_parse_legacy_url(bstr0(st->path), f); + const char *f_names[4] = {"username", "hostname", "port", "filename"}; for (int n = 0; n < 4; n++) { if (f[n].len) { const char *opt = find_url_opt(st, f_names[n]); diff --git a/stream/stream.h b/stream/stream.h index 9ee1df25aa..90545da087 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -296,6 +296,13 @@ void mp_setup_av_network_options(struct AVDictionary **dict, struct mpv_global *global, struct mp_log *log); +// sort-of legacy handling of options-in-stream-URL +#define URL_USERNAME 0 +#define URL_HOSTNAME 1 +#define URL_PORT 2 +#define URL_FILENAME 3 +void mp_parse_legacy_url(bstr url, bstr components[4]); + void stream_print_proto_list(struct mp_log *log); char **stream_get_proto_list(void); bool stream_has_proto(const char *proto); diff --git a/stream/stream_dvd.c b/stream/stream_dvd.c index 55cb6dfc7b..4b423de630 100644 --- a/stream/stream_dvd.c +++ b/stream/stream_dvd.c @@ -45,7 +45,7 @@ #define FIRST_PCM_AID 160 #include "stream.h" -#include "options/m_option.h" +#include "options/m_config.h" #include "options/options.h" #include "options/path.h" @@ -109,18 +109,6 @@ typedef struct { char *cfg_device; } dvd_priv_t; -static const dvd_priv_t stream_priv_dflts = { - .cfg_title = 0, -}; - -#define OPT_BASE_STRUCT dvd_priv_t -/// URL definition -static const m_option_t stream_opts_fields[] = { - OPT_INTRANGE("title", cfg_title, 0, 0, 99), - OPT_STRING("device", cfg_device, 0), - {0} -}; - static int dvd_lang_from_aid(stream_t *stream, int id) { dvd_priv_t *d; int i; @@ -657,12 +645,15 @@ static int control(stream_t *stream,int cmd,void* arg) } -static int open_s(stream_t *stream) +static int open_s_internal(stream_t *stream) { int k; dvd_priv_t *d = stream->priv; - d->dvd_angle = stream->opts->dvd_angle; + struct dvd_opts *opts = + mp_get_config_group(stream, stream->global, &dvd_conf); + + d->dvd_angle = opts->angle; MP_VERBOSE(stream, "URL: %s\n", stream->url); d->dvd_title = d->cfg_title + 1; @@ -680,11 +671,11 @@ static int open_s(stream_t *stream) */ if(d->cfg_device && d->cfg_device[0]) d->dvd_device_current = d->cfg_device; - else if(stream->opts->dvd_device && stream->opts->dvd_device[0]) - d->dvd_device_current = talloc_strdup(stream, stream->opts->dvd_device); + else if(opts->device && opts->device[0]) + d->dvd_device_current = talloc_strdup(stream, opts->device); else d->dvd_device_current = DEFAULT_DVD_DEVICE; - d->dvd_speed = stream->opts->dvd_speed; + d->dvd_speed = opts->speed; dvd_set_speed(stream,d->dvd_device_current, d->dvd_speed); #if defined(__APPLE__) || defined(__DARWIN__) /* Dynamic DVD drive selection on Darwin */ @@ -933,11 +924,32 @@ fail: return STREAM_UNSUPPORTED; } +static int open_s(stream_t *stream) +{ + dvd_priv_t *d = talloc_zero(stream, dvd_priv_t); + stream->priv = d; + + bstr title, bdevice; + bstr_split_tok(bstr0(stream->path), "/", &title, &bdevice); + + if (title.len) { + bstr rest; + d->cfg_title = bstrtoll(title, &rest, 10); + if (rest.len) { + MP_ERR(stream, "number expected: '%.*s'\n", BSTR_P(rest)); + return STREAM_ERROR; + } + } + + d->cfg_device = bstrto0(d, bdevice); + + return open_s_internal(stream); +} + static int ifo_stream_open(stream_t *stream) { - dvd_priv_t *priv = talloc_ptrtype(stream, priv); + dvd_priv_t *priv = talloc_zero(stream, dvd_priv_t); stream->priv = priv; - *priv = stream_priv_dflts; char *path = mp_file_get_path(priv, bstr0(stream->url)); if (!path) @@ -958,7 +970,7 @@ static int ifo_stream_open(stream_t *stream) priv->cfg_device = bstrto0(priv, mp_dirname(path)); MP_INFO(stream, ".IFO detected. Redirecting to dvdread://\n"); - return open_s(stream); + return open_s_internal(stream); unsupported: talloc_free(priv); @@ -970,14 +982,6 @@ const stream_info_t stream_info_dvd = { .name = "dvd", .open = open_s, .protocols = (const char*const[]){ "dvdread", NULL }, - .priv_size = sizeof(dvd_priv_t), - .priv_defaults = &stream_priv_dflts, - .options = stream_opts_fields, - .url_options = (const char*const[]){ - "hostname=title", - "filename=device", - NULL - }, }; const stream_info_t stream_info_ifo = { diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c index d61ca5c937..ec15c83b20 100644 --- a/stream/stream_dvdnav.c +++ b/stream/stream_dvdnav.c @@ -34,7 +34,7 @@ #include "options/options.h" #include "common/msg.h" #include "input/input.h" -#include "options/m_option.h" +#include "options/m_config.h" #include "options/path.h" #include "osdep/timer.h" #include "stream.h" @@ -59,19 +59,8 @@ struct priv { int track; char *device; -}; -static const struct priv stream_priv_dflts = { - .track = TITLE_LONGEST, -}; - -#define OPT_BASE_STRUCT struct priv -static const m_option_t stream_opts_fields[] = { - OPT_CHOICE_OR_INT("title", track, 0, 0, 99, - ({"menu", TITLE_MENU}, - {"longest", TITLE_LONGEST})), - OPT_STRING("device", device, 0), - {0} + struct dvd_opts *opts; }; #define DNE(e) [e] = # e @@ -437,7 +426,7 @@ static struct priv *new_dvdnav_stream(stream_t *stream, char *filename) if (!(priv->filename = strdup(filename))) return NULL; - priv->dvd_speed = stream->opts->dvd_speed; + priv->dvd_speed = priv->opts->speed; dvd_set_speed(stream, priv->filename, priv->dvd_speed); if (dvdnav_open(&(priv->dvdnav), priv->filename) != DVDNAV_STATUS_OK) { @@ -458,16 +447,18 @@ static struct priv *new_dvdnav_stream(stream_t *stream, char *filename) return priv; } -static int open_s(stream_t *stream) +static int open_s_internal(stream_t *stream) { struct priv *priv, *p; priv = p = stream->priv; char *filename; + p->opts = mp_get_config_group(stream, stream->global, &dvd_conf); + if (p->device && p->device[0]) filename = p->device; - else if (stream->opts->dvd_device && stream->opts->dvd_device[0]) - filename = stream->opts->dvd_device; + else if (p->opts->device && p->opts->device[0]) + filename = p->opts->device; else filename = DEFAULT_DVD_DEVICE; if (!new_dvdnav_stream(stream, filename)) { @@ -509,8 +500,8 @@ static int open_s(stream_t *stream) MP_FATAL(stream, "DVD menu support has been removed.\n"); return STREAM_ERROR; } - if (stream->opts->dvd_angle > 1) - dvdnav_angle_change(priv->dvdnav, stream->opts->dvd_angle); + if (p->opts->angle > 1) + dvdnav_angle_change(priv->dvdnav, p->opts->angle); stream->sector_size = 2048; stream->fill_buffer = fill_buffer; @@ -524,18 +515,38 @@ static int open_s(stream_t *stream) return STREAM_OK; } +static int open_s(stream_t *stream) +{ + struct priv *priv = talloc_zero(stream, struct priv); + stream->priv = priv; + + bstr title, bdevice; + bstr_split_tok(bstr0(stream->path), "/", &title, &bdevice); + + priv->track = TITLE_LONGEST; + + if (bstr_equals0(title, "longest") || bstr_equals0(title, "first")) { + priv->track = TITLE_LONGEST; + } else if (bstr_equals0(title, "menu")) { + priv->track = TITLE_MENU; + } else if (title.len) { + bstr rest; + priv->title = bstrtoll(title, &rest, 10); + if (rest.len) { + MP_ERR(stream, "number expected: '%.*s'\n", BSTR_P(rest)); + return STREAM_ERROR; + } + } + + priv->device = bstrto0(priv, bdevice); + + return open_s_internal(stream); +} + const stream_info_t stream_info_dvdnav = { .name = "dvdnav", .open = open_s, .protocols = (const char*const[]){ "dvd", "dvdnav", NULL }, - .priv_size = sizeof(struct priv), - .priv_defaults = &stream_priv_dflts, - .options = stream_opts_fields, - .url_options = (const char*const[]){ - "hostname=title", - "filename=device", - NULL - }, }; static bool check_ifo(const char *path) @@ -548,9 +559,10 @@ static bool check_ifo(const char *path) static int ifo_dvdnav_stream_open(stream_t *stream) { - struct priv *priv = talloc_ptrtype(stream, priv); + struct priv *priv = talloc_zero(stream, struct priv); stream->priv = priv; - *priv = stream_priv_dflts; + + priv->track = TITLE_LONGEST; char *path = mp_file_get_path(priv, bstr0(stream->url)); if (!path) @@ -572,7 +584,7 @@ static int ifo_dvdnav_stream_open(stream_t *stream) priv->device = bstrto0(priv, mp_dirname(path)); MP_INFO(stream, ".IFO detected. Redirecting to dvd://\n"); - return open_s(stream); + return open_s_internal(stream); unsupported: talloc_free(priv);