summaryrefslogtreecommitdiffstats
path: root/stream/stream_bluray.c
diff options
context:
space:
mode:
Diffstat (limited to 'stream/stream_bluray.c')
-rw-r--r--stream/stream_bluray.c155
1 files changed, 90 insertions, 65 deletions
diff --git a/stream/stream_bluray.c b/stream/stream_bluray.c
index 2a9c864402..26a78e5f21 100644
--- a/stream/stream_bluray.c
+++ b/stream/stream_bluray.c
@@ -41,8 +41,7 @@
#include "mpv_talloc.h"
#include "common/common.h"
#include "common/msg.h"
-#include "options/m_option.h"
-#include "options/options.h"
+#include "options/m_config.h"
#include "options/path.h"
#include "stream.h"
#include "osdep/timer.h"
@@ -54,6 +53,7 @@
#define BLURAY_DEFAULT_ANGLE 0
#define BLURAY_DEFAULT_CHAPTER 0
+#define BLURAY_PLAYLIST_TITLE -3
#define BLURAY_DEFAULT_TITLE -2
#define BLURAY_MENU_TITLE -1
@@ -81,36 +81,12 @@ struct bluray_priv_s {
int current_playlist;
int cfg_title;
+ int cfg_playlist;
char *cfg_device;
bool use_nav;
};
-static const struct bluray_priv_s bluray_stream_priv_dflts = {
- .cfg_title = BLURAY_DEFAULT_TITLE,
-};
-
-static const struct bluray_priv_s bdnav_stream_priv_dflts = {
- .cfg_title = BLURAY_DEFAULT_TITLE,
- .use_nav = true,
-};
-
-#define OPT_BASE_STRUCT struct bluray_priv_s
-static const m_option_t bluray_stream_opts_fields[] = {
- OPT_CHOICE_OR_INT("title", cfg_title, 0, 0, 99999,
- ({"longest", BLURAY_DEFAULT_TITLE})),
- OPT_STRING("device", cfg_device, 0),
- {0}
-};
-
-static const m_option_t bdnav_stream_opts_fields[] = {
- OPT_CHOICE_OR_INT("title", cfg_title, 0, 0, 99999,
- ({"menu", BLURAY_MENU_TITLE},
- {"first", BLURAY_DEFAULT_TITLE})),
- OPT_STRING("device", cfg_device, 0),
- {0}
-};
-
static void destruct(struct bluray_priv_s *priv)
{
if (priv->title_info)
@@ -118,6 +94,11 @@ static void destruct(struct bluray_priv_s *priv)
bd_close(priv->bd);
}
+inline static int play_playlist(struct bluray_priv_s *priv, int playlist)
+{
+ return bd_select_playlist(priv->bd, playlist);
+}
+
inline static int play_title(struct bluray_priv_s *priv, int title)
{
return bd_select_title(priv->bd, title);
@@ -367,34 +348,42 @@ static bool check_disc_info(stream_t *s)
static void select_initial_title(stream_t *s, int title_guess) {
struct bluray_priv_s *b = s->priv;
- int title = -1;
- if (b->cfg_title != BLURAY_DEFAULT_TITLE )
- title = b->cfg_title;
- else
- title = title_guess;
- if (title < 0)
- return;
-
- if (play_title(b, title))
- b->current_title = title;
- else {
- MP_WARN(s, "Couldn't start title '%d'.\n", title);
+ if (b->cfg_title == BLURAY_PLAYLIST_TITLE) {
+ if (!play_playlist(b, b->cfg_playlist))
+ MP_WARN(s, "Couldn't start playlist '%05d'.\n", b->cfg_playlist);
b->current_title = bd_get_current_title(b->bd);
+ } else {
+ int title = -1;
+ if (b->cfg_title != BLURAY_DEFAULT_TITLE )
+ title = b->cfg_title;
+ else
+ title = title_guess;
+ if (title < 0)
+ return;
+
+ if (play_title(b, title))
+ b->current_title = title;
+ else {
+ MP_WARN(s, "Couldn't start title '%d'.\n", title);
+ b->current_title = bd_get_current_title(b->bd);
+ }
}
}
-static int bluray_stream_open(stream_t *s)
+static int bluray_stream_open_internal(stream_t *s)
{
struct bluray_priv_s *b = s->priv;
- const char *device = NULL;
+ char *device = NULL;
/* find the requested device */
- if (b->cfg_device && b->cfg_device[0])
+ if (b->cfg_device && b->cfg_device[0]) {
device = b->cfg_device;
- else if (s->opts->bluray_device && s->opts->bluray_device[0])
- device = s->opts->bluray_device;
+ } else {
+ mp_read_option_raw(s->global, "bluray-device", &m_option_type_string,
+ &device);
+ }
- if (!device) {
+ if (!device || !device[0]) {
MP_ERR(s, "No Blu-ray device/location was specified ...\n");
return STREAM_UNSUPPORTED;
}
@@ -434,9 +423,10 @@ static int bluray_stream_open(stream_t *s)
if (!ti)
continue;
+ char *time = mp_format_time(ti->duration / 90000, false);
MP_VERBOSE(s, "idx: %3d duration: %s (playlist: %05d.mpls)\n",
- i + 1, mp_format_time(ti->duration / 90000, false),
- ti->playlist);
+ i + 1, time, ti->playlist);
+ talloc_free(time);
/* try to guess which title may contain the main movie */
if (ti->duration > max_duration) {
@@ -470,32 +460,65 @@ static int bluray_stream_open(stream_t *s)
return STREAM_OK;
}
+const stream_info_t stream_info_bdnav;
+
+static int bluray_stream_open(stream_t *s)
+{
+ struct bluray_priv_s *b = talloc_zero(s, struct bluray_priv_s);
+ s->priv = b;
+
+ b->use_nav = s->info == &stream_info_bdnav;
+
+ bstr title, bdevice, rest = { .len = 0 };
+ bstr_split_tok(bstr0(s->path), "/", &title, &bdevice);
+
+ b->cfg_title = BLURAY_DEFAULT_TITLE;
+
+ if (bstr_equals0(title, "longest") || bstr_equals0(title, "first")) {
+ b->cfg_title = BLURAY_DEFAULT_TITLE;
+ } else if (bstr_equals0(title, "menu")) {
+ b->cfg_title = BLURAY_MENU_TITLE;
+ } else if (bstr_equals0(title, "mpls")) {
+ bstr_split_tok(bdevice, "/", &title, &bdevice);
+ long long pl = bstrtoll(title, &rest, 10);
+ if (rest.len) {
+ MP_ERR(s, "number expected: '%.*s'\n", BSTR_P(rest));
+ return STREAM_ERROR;
+ } else if (pl < 0 || 99999 < pl) {
+ MP_ERR(s, "invalid playlist: '%.*s', must be in the range 0-99999\n",
+ BSTR_P(title));
+ return STREAM_ERROR;
+ }
+ b->cfg_playlist = pl;
+ b->cfg_title = BLURAY_PLAYLIST_TITLE;
+ } else if (title.len) {
+ long long t = bstrtoll(title, &rest, 10);
+ if (rest.len) {
+ MP_ERR(s, "number expected: '%.*s'\n", BSTR_P(rest));
+ return STREAM_ERROR;
+ } else if (t < 0 || 99999 < t) {
+ MP_ERR(s, "invalid title: '%.*s', must be in the range 0-99999\n",
+ BSTR_P(title));
+ return STREAM_ERROR;
+ }
+ b->cfg_title = t;
+ }
+
+ b->cfg_device = bstrto0(b, bdevice);
+
+ return bluray_stream_open_internal(s);
+}
+
const stream_info_t stream_info_bluray = {
.name = "bd",
.open = bluray_stream_open,
.protocols = (const char*const[]){ "bd", "br", "bluray", NULL },
- .priv_defaults = &bluray_stream_priv_dflts,
- .priv_size = sizeof(struct bluray_priv_s),
- .options = bluray_stream_opts_fields,
- .url_options = (const char*const[]){
- "hostname=title",
- "filename=device",
- NULL
- },
};
const stream_info_t stream_info_bdnav = {
.name = "bdnav",
.open = bluray_stream_open,
.protocols = (const char*const[]){ "bdnav", "brnav", "bluraynav", NULL },
- .priv_defaults = &bdnav_stream_priv_dflts,
- .priv_size = sizeof(struct bluray_priv_s),
- .options = bdnav_stream_opts_fields,
- .url_options = (const char*const[]){
- "hostname=title",
- "filename=device",
- NULL
- },
};
static bool check_bdmv(const char *path)
@@ -542,7 +565,9 @@ static int bdmv_dir_stream_open(stream_t *stream)
{
struct bluray_priv_s *priv = talloc_ptrtype(stream, priv);
stream->priv = priv;
- *priv = bluray_stream_priv_dflts;
+ *priv = (struct bluray_priv_s){
+ .cfg_title = BLURAY_DEFAULT_TITLE,
+ };
char *path = mp_file_get_path(priv, bstr0(stream->url));
if (!path)
@@ -569,7 +594,7 @@ static int bdmv_dir_stream_open(stream_t *stream)
goto unsupported;
MP_INFO(stream, "BDMV detected. Redirecting to bluray://\n");
- return bluray_stream_open(stream);
+ return bluray_stream_open_internal(stream);
unsupported:
talloc_free(priv);