stream: redo URL parsing, replace m_struct usage with m_config

Move the URL parsing code from m_option.c to stream.c, and simplify it
dramatically. This code originates from times when http code used this,
but now it's just relict from other stream implementations reusing this
code. Remove the unused bits and simplify the rest.

stream_vcd is insane, and the priv struct is different on every
platform, so drop the URL parsing. This means you can't specify a track
anymore, only the device. (Does anyone use stream_vcd? Not like this
couldn't be fixed, but it doesn't seem worth the effort, especially
because it'd require potentially touching platform specific code.)
This commit is contained in:
wm4
2013-08-02 17:02:34 +02:00
parent 964194b55b
commit bc1d61cf42
22 changed files with 282 additions and 593 deletions

View File

@@ -27,7 +27,7 @@ SYNOPSIS
| **mpv** [options] {group of files and options} | **mpv** [options] {group of files and options}
| **mpv** [bd]://[title][/device] [options] | **mpv** [bd]://[title][/device] [options]
| **mpv** dvd://[title|[start\_title]-end\_title][/device] [options] | **mpv** dvd://[title|[start\_title]-end\_title][/device] [options]
| **mpv** \vcd://track[/device] | **mpv** \vcd://[/device]
| **mpv** \tv://[channel][/input_id] [options] | **mpv** \tv://[channel][/input_id] [options]
| **mpv** radio://[channel|frequency][/capture] [options] | **mpv** radio://[channel|frequency][/capture] [options]
| **mpv** \pvr:// [options] | **mpv** \pvr:// [options]

View File

@@ -2407,225 +2407,3 @@ const m_option_type_t m_option_type_obj_settings_list = {
.copy = copy_obj_settings_list, .copy = copy_obj_settings_list,
.free = free_obj_settings_list, .free = free_obj_settings_list,
}; };
/* Replace escape sequences in an URL (or a part of an URL) */
/* works like strcpy(), but without return argument,
except that outbuf == inbuf is allowed */
static void url_unescape_string(char *outbuf, const char *inbuf)
{
unsigned char c,c1,c2;
int i,len=strlen(inbuf);
for (i=0;i<len;i++) {
c = inbuf[i];
if (c == '%' && i<len-2) { //must have 2 more chars
c1 = toupper(inbuf[i+1]); // we need uppercase characters
c2 = toupper(inbuf[i+2]);
if (((c1>='0' && c1<='9') || (c1>='A' && c1<='F')) &&
((c2>='0' && c2<='9') || (c2>='A' && c2<='F')) )
{
if (c1>='0' && c1<='9')
c1-='0';
else
c1-='A'-10;
if (c2>='0' && c2<='9')
c2-='0';
else
c2-='A'-10;
c = (c1<<4) + c2;
i=i+2; //only skip next 2 chars if valid esc
}
}
*outbuf++ = c;
}
*outbuf++='\0'; //add nullterm to string
}
static int parse_custom_url(const m_option_t *opt, struct bstr name,
struct bstr url, void *dst)
{
int r;
m_struct_t *desc = opt->priv;
if (!desc) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: Custom URL needs "
"a pointer to a m_struct_t in the priv field.\n", BSTR_P(name));
return M_OPT_PARSER_ERR;
}
// extract the protocol
int idx = bstr_find0(url, "://");
if (idx < 0) {
// Filename only
if (m_option_list_find(desc->fields, "filename")) {
m_struct_set(desc, dst, "filename", url);
return 1;
}
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Option %.*s: URL doesn't have a valid protocol!\n",
BSTR_P(name));
return M_OPT_INVALID;
}
struct bstr ptr1 = bstr_cut(url, idx + 3);
if (m_option_list_find(desc->fields, "string")) {
if (ptr1.len > 0) {
m_struct_set(desc, dst, "string", ptr1);
return 1;
}
}
if (dst && m_option_list_find(desc->fields, "protocol")) {
r = m_struct_set(desc, dst, "protocol", bstr_splice(url, 0, idx));
if (r < 0) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Option %.*s: Error while setting protocol.\n",
BSTR_P(name));
return r;
}
}
// check if a username:password is given
idx = bstrchr(ptr1, '/');
if (idx < 0)
idx = ptr1.len;
struct bstr hostpart = bstr_splice(ptr1, 0, idx);
struct bstr path = bstr_cut(ptr1, idx);
idx = bstrchr(hostpart, '@');
if (idx >= 0) {
struct bstr userpass = bstr_splice(hostpart, 0, idx);
hostpart = bstr_cut(hostpart, idx + 1);
// We got something, at least a username...
if (!m_option_list_find(desc->fields, "username")) {
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
"Option %.*s: This URL doesn't have a username part.\n",
BSTR_P(name));
// skip
} else {
idx = bstrchr(userpass, ':');
if (idx >= 0) {
// We also have a password
if (!m_option_list_find(desc->fields, "password")) {
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
"Option %.*s: This URL doesn't have a password part.\n",
BSTR_P(name));
// skip
} else { // Username and password
if (dst) {
r = m_struct_set(desc, dst, "username",
bstr_splice(userpass, 0, idx));
if (r < 0) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Option %.*s: Error while setting username.\n",
BSTR_P(name));
return r;
}
r = m_struct_set(desc, dst, "password",
bstr_splice(userpass, idx+1,
userpass.len));
if (r < 0) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Option %.*s: Error while setting password.\n",
BSTR_P(name));
return r;
}
}
}
} else { // User name only
r = m_struct_set(desc, dst, "username", userpass);
if (r < 0) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Option %.*s: Error while setting username.\n",
BSTR_P(name));
return r;
}
}
}
}
// Before looking for a port number check if we have an IPv6 type
// numeric address.
// In an IPv6 URL the numeric address should be inside square braces.
int idx1 = bstrchr(hostpart, '[');
int idx2 = bstrchr(hostpart, ']');
struct bstr portstr = hostpart;
bool v6addr = false;
if (idx1 >= 0 && idx2 >= 0 && idx1 < idx2) {
// we have an IPv6 numeric address
portstr = bstr_cut(hostpart, idx2);
hostpart = bstr_splice(hostpart, idx1 + 1, idx2);
v6addr = true;
}
idx = bstrchr(portstr, ':');
if (idx >= 0) {
if (!v6addr)
hostpart = bstr_splice(hostpart, 0, idx);
// We have an URL beginning like http://www.hostname.com:1212
// Get the port number
if (!m_option_list_find(desc->fields, "port")) {
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
"Option %.*s: This URL doesn't have a port part.\n",
BSTR_P(name));
// skip
} else {
if (dst) {
int p = bstrtoll(bstr_cut(portstr, idx + 1), NULL, 0);
char tmp[100];
snprintf(tmp, 99, "%d", p);
r = m_struct_set(desc, dst, "port", bstr0(tmp));
if (r < 0) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Option %.*s: Error while setting port.\n",
BSTR_P(name));
return r;
}
}
}
}
// Get the hostname
if (hostpart.len > 0) {
if (!m_option_list_find(desc->fields, "hostname")) {
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
"Option %.*s: This URL doesn't have a hostname part.\n",
BSTR_P(name));
// skip
} else {
r = m_struct_set(desc, dst, "hostname", hostpart);
if (r < 0) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Option %.*s: Error while setting hostname.\n",
BSTR_P(name));
return r;
}
}
}
// Look if a path is given
if (path.len > 1) { // not just "/"
// copy the path/filename in the URL container
if (!m_option_list_find(desc->fields, "filename")) {
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
"Option %.*s: This URL doesn't have a filename part.\n",
BSTR_P(name));
// skip
} else {
if (dst) {
char *fname = bstrdup0(NULL, bstr_cut(path, 1));
url_unescape_string(fname, fname);
r = m_struct_set(desc, dst, "filename", bstr0(fname));
talloc_free(fname);
if (r < 0) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Option %.*s: Error while setting filename.\n",
BSTR_P(name));
return r;
}
}
}
}
return 1;
}
/// TODO : Write the other needed funcs for 'normal' options
const m_option_type_t m_option_type_custom_url = {
.name = "Custom URL",
.parse = parse_custom_url,
};

View File

@@ -155,12 +155,6 @@ int m_obj_parse_sub_config(struct bstr opt_name, struct bstr name,
struct bstr *pstr, struct m_config *config, struct bstr *pstr, struct m_config *config,
int flags, char ***ret); int flags, char ***ret);
// Parse an URL into a struct.
/** The option priv field (\ref m_option::priv) must point to a
* \ref m_struct_st describing which fields of the URL must be used.
*/
extern const m_option_type_t m_option_type_custom_url;
struct m_opt_choice_alternatives { struct m_opt_choice_alternatives {
char *name; char *name;
int value; int value;
@@ -193,7 +187,6 @@ struct m_sub_options {
#define CONF_TYPE_FOURCC (&m_option_type_fourcc) #define CONF_TYPE_FOURCC (&m_option_type_fourcc)
#define CONF_TYPE_AFMT (&m_option_type_afmt) #define CONF_TYPE_AFMT (&m_option_type_afmt)
#define CONF_TYPE_OBJ_SETTINGS_LIST (&m_option_type_obj_settings_list) #define CONF_TYPE_OBJ_SETTINGS_LIST (&m_option_type_obj_settings_list)
#define CONF_TYPE_CUSTOM_URL (&m_option_type_custom_url)
#define CONF_TYPE_TIME (&m_option_type_time) #define CONF_TYPE_TIME (&m_option_type_time)
#define CONF_TYPE_CHOICE (&m_option_type_choice) #define CONF_TYPE_CHOICE (&m_option_type_choice)
#define CONF_TYPE_INT_PAIR (&m_option_type_intpair) #define CONF_TYPE_INT_PAIR (&m_option_type_intpair)

View File

@@ -90,6 +90,10 @@ typedef struct {
int retry; int retry;
int timeout; int timeout;
int last_freq; int last_freq;
char *cfg_prog;
int cfg_card;
int cfg_timeout;
} dvb_priv_t; } dvb_priv_t;

View File

@@ -44,7 +44,7 @@
#include "demux/demux.h" #include "demux/demux.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/m_struct.h" #include "core/m_config.h"
// Includes additional padding in case sizes get rounded up by sector size. // Includes additional padding in case sizes get rounded up by sector size.
#define TOTAL_BUFFER_SIZE (STREAM_MAX_BUFFER_SIZE + STREAM_MAX_SECTOR_SIZE) #define TOTAL_BUFFER_SIZE (STREAM_MAX_BUFFER_SIZE + STREAM_MAX_SECTOR_SIZE)
@@ -114,40 +114,97 @@ static const stream_info_t *const auto_open_streams[] = {
NULL NULL
}; };
static stream_t *new_stream(size_t min_size);
static int stream_seek_unbuffered(stream_t *s, int64_t newpos); static int stream_seek_unbuffered(stream_t *s, int64_t newpos);
static stream_t *open_stream_plugin(const stream_info_t *sinfo, static const char *find_url_opt(struct stream *s, const char *opt)
const char *filename, int mode,
struct MPOpts *options, int *ret)
{ {
void *arg = NULL; for (int n = 0; s->info->url_options && s->info->url_options[n][0]; n++) {
stream_t *s; if (strcmp(s->info->url_options[n][0], opt) == 0)
m_struct_t *desc = (m_struct_t *)sinfo->opts; return s->info->url_options[n][1];
}
return NULL;
}
// Parse options static bstr split_next(bstr *s, char end, const char *delim)
if (desc) { {
arg = m_struct_alloc(desc); int idx = bstrcspn(*s, delim);
if (sinfo->opts_url) { if (end && (idx >= s->len || s->start[idx] != end))
m_option_t url_opt = { "stream url", arg, CONF_TYPE_CUSTOM_URL, 0, return (bstr){0};
0, 0, (void *)sinfo->opts }; bstr r = bstr_splice(*s, 0, idx);
if (m_option_parse(&url_opt, bstr0("stream url"), bstr0(filename), *s = bstr_cut(*s, idx + (end ? 1 : 0));
arg) < 0) return r;
{ }
mp_tmsg(MSGT_OPEN, MSGL_ERR, "URL parsing failed on url %s\n",
filename); // Parse the stream URL, syntax:
m_struct_free(desc, arg); // proto:// [<username>@]<hostname>[:<port>][/<filename>]
*ret = STREAM_ERROR; // (the proto:// part is already removed from s->path)
return NULL; // This code originates from times when http code used this, but now it's
// just relict from other stream implementations reusing this code.
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};
for (int n = 0; n < 4; n++) {
if (f[n].len) {
const char *opt = find_url_opt(st, f_names[n]);
if (!opt) {
mp_tmsg(MSGT_OPEN, MSGL_ERR, "Stream type '%s' accepts no '%s' "
"field in URLs.\n", st->info->name, f_names[n]);
return false;
}
int r = m_config_set_option(config, bstr0(opt), f[n]);
if (r < 0) {
mp_tmsg(MSGT_OPEN, MSGL_ERR, "Error setting stream option: %s\n",
m_option_strerror(r));
return false;
} }
} }
} }
s = new_stream(0); return true;
}
static stream_t *new_stream(void)
{
stream_t *s = talloc_size(NULL, sizeof(stream_t) + TOTAL_BUFFER_SIZE);
memset(s, 0, sizeof(stream_t));
return s;
}
static stream_t *open_stream_plugin(const stream_info_t *sinfo,
const char *url, const char *path, int mode,
struct MPOpts *options, int *ret)
{
stream_t *s = new_stream();
s->info = sinfo;
s->opts = options; s->opts = options;
s->url = talloc_strdup(s, filename); s->url = talloc_strdup(s, url);
s->path = talloc_strdup(s, path);
// Parse options
if (sinfo->priv_size) {
struct m_obj_desc desc = {
.priv_size = sinfo->priv_size,
.priv_defaults = sinfo->priv_defaults,
.options = sinfo->options,
};
struct m_config *config = m_config_from_obj_desc(s, &desc);
s->priv = config->optstruct;
if (s->info->url_options && !parse_url(s, config)) {
mp_tmsg(MSGT_OPEN, MSGL_ERR, "URL parsing failed on url %s\n", url);
talloc_free(s);
*ret = STREAM_ERROR;
return NULL;
}
}
s->flags = 0; s->flags = 0;
s->mode = mode; s->mode = mode;
*ret = sinfo->open(s, mode, arg); *ret = sinfo->open(s, mode);
if ((*ret) != STREAM_OK) { if ((*ret) != STREAM_OK) {
talloc_free(s); talloc_free(s);
return NULL; return NULL;
@@ -165,7 +222,7 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
s->uncached_type = s->type; s->uncached_type = s->type;
mp_msg(MSGT_OPEN, MSGL_V, "[stream] [%s] %s\n", sinfo->name, filename); mp_msg(MSGT_OPEN, MSGL_V, "[stream] [%s] %s\n", sinfo->name, url);
if (s->mime_type) if (s->mime_type)
mp_msg(MSGT_OPEN, MSGL_V, "Mime-type: '%s'\n", s->mime_type); mp_msg(MSGT_OPEN, MSGL_V, "Mime-type: '%s'\n", s->mime_type);
@@ -173,15 +230,28 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
return s; return s;
} }
static const char *match_proto(const char *url, const char *proto)
{
int l = strlen(proto);
if (l > 0) {
if (strncasecmp(url, proto, l) == 0 && strncmp("://", url + l, 3) == 0)
return url + l + 3;
} else {
// pure filenames
if (!strstr(url, "://"))
return url;
}
return NULL;
}
static stream_t *open_stream_full(const char *filename, int mode, static stream_t *open_stream_full(const char *url, int mode,
struct MPOpts *options) struct MPOpts *options)
{ {
int i, j, l, r; int i, j, r;
const stream_info_t *sinfo; const stream_info_t *sinfo;
stream_t *s; stream_t *s;
assert(filename); assert(url);
for (i = 0; auto_open_streams[i]; i++) { for (i = 0; auto_open_streams[i]; i++) {
sinfo = auto_open_streams[i]; sinfo = auto_open_streams[i];
@@ -192,17 +262,13 @@ static stream_t *open_stream_full(const char *filename, int mode,
continue; continue;
} }
for (j = 0; sinfo->protocols[j]; j++) { for (j = 0; sinfo->protocols[j]; j++) {
l = strlen(sinfo->protocols[j]); const char *path = match_proto(url, sinfo->protocols[j]);
// l == 0 => Don't do protocol matching (ie network and filenames) if (path) {
if ((l == 0 && !strstr(filename, "://")) || s = open_stream_plugin(sinfo, url, path, mode, options, &r);
((strncasecmp(sinfo->protocols[j], filename, l) == 0) &&
(strncmp("://", filename + l, 3) == 0))) {
s = open_stream_plugin(sinfo, filename, mode, options, &r);
if (s) if (s)
return s; return s;
if (r != STREAM_UNSUPPORTED) { if (r != STREAM_UNSUPPORTED) {
mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to open %s.\n", mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to open %s.\n", url);
filename);
return NULL; return NULL;
} }
break; break;
@@ -210,7 +276,7 @@ static stream_t *open_stream_full(const char *filename, int mode,
} }
} }
mp_tmsg(MSGT_OPEN, MSGL_ERR, "No stream found to handle url %s\n", filename); mp_tmsg(MSGT_OPEN, MSGL_ERR, "No stream found to handle url %s\n", url);
return NULL; return NULL;
} }
@@ -558,14 +624,6 @@ void stream_update_size(stream_t *s)
} }
} }
static stream_t *new_stream(size_t min_size)
{
min_size = FFMAX(min_size, TOTAL_BUFFER_SIZE);
stream_t *s = talloc_size(NULL, sizeof(stream_t) + min_size);
memset(s, 0, sizeof(stream_t));
return s;
}
void free_stream(stream_t *s) void free_stream(stream_t *s)
{ {
if (!s) if (!s)
@@ -638,7 +696,7 @@ static int stream_enable_cache(stream_t **stream, int64_t size, int64_t min,
// Can't handle a loaded buffer. // Can't handle a loaded buffer.
orig->buf_len = orig->buf_pos = 0; orig->buf_len = orig->buf_pos = 0;
stream_t *cache = new_stream(0); stream_t *cache = new_stream();
cache->uncached_type = orig->type; cache->uncached_type = orig->type;
cache->uncached_stream = orig; cache->uncached_stream = orig;
cache->flags |= MP_STREAM_SEEK; cache->flags |= MP_STREAM_SEEK;

View File

@@ -109,15 +109,17 @@ struct stream;
typedef struct stream_info_st { typedef struct stream_info_st {
const char *name; const char *name;
// opts is set from ->opts // opts is set from ->opts
int (*open)(struct stream *st, int mode, void *opts); int (*open)(struct stream *st, int mode);
const char *protocols[MAX_STREAM_PROTOCOLS]; const char *protocols[MAX_STREAM_PROTOCOLS];
const void *opts; int priv_size;
int opts_url; /* If this is 1 we will parse the url as an option string const void *priv_defaults;
* too. Otherwise options are only parsed from the const struct m_option *options;
* options string given to open_stream_plugin */ const char *url_options[][2];
} stream_info_t; } stream_info_t;
typedef struct stream { typedef struct stream {
const struct stream_info_st *info;
// Read // Read
int (*fill_buffer)(struct stream *s, char *buffer, int max_len); int (*fill_buffer)(struct stream *s, char *buffer, int max_len);
// Write // Write
@@ -142,7 +144,8 @@ typedef struct stream {
int mode; //STREAM_READ or STREAM_WRITE int mode; //STREAM_READ or STREAM_WRITE
bool streaming; // known to be a network stream if true bool streaming; // known to be a network stream if true
void *priv; // used for DVD, TV, RTSP etc void *priv; // used for DVD, TV, RTSP etc
char *url; // strdup() of filename/url char *url; // filename/url (possibly including protocol prefix)
char *path; // filename (url without protocol prefix)
char *mime_type; // when HTTP streaming is used char *mime_type; // when HTTP streaming is used
char *demuxer; // request demuxer to be used char *demuxer; // request demuxer to be used
char *lavf_type; // name of expected demuxer type for lavf char *lavf_type; // name of expected demuxer type for lavf

View File

@@ -25,7 +25,7 @@ static int fill_buffer(stream_t *s, char *buffer, int max_len)
return -1; return -1;
} }
static int open_f(stream_t *stream, int mode, void *opts) static int open_f(stream_t *stream, int mode)
{ {
if (mode != STREAM_READ) if (mode != STREAM_READ)
return STREAM_ERROR; return STREAM_ERROR;

View File

@@ -38,7 +38,6 @@
#include "config.h" #include "config.h"
#include "talloc.h" #include "talloc.h"
#include "core/mp_msg.h" #include "core/mp_msg.h"
#include "core/m_struct.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "stream.h" #include "stream.h"
#include "demux/stheader.h" #include "demux/stheader.h"
@@ -61,9 +60,12 @@ struct bluray_priv_s {
BLURAY *bd; BLURAY *bd;
int current_angle; int current_angle;
int current_title; int current_title;
int cfg_title;
char *cfg_device;
}; };
static struct stream_priv_s { static const struct stream_priv_s {
int title; int title;
char *device; char *device;
} bluray_stream_priv_dflts = { } bluray_stream_priv_dflts = {
@@ -71,18 +73,11 @@ static struct stream_priv_s {
NULL NULL
}; };
#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f) #define OPT_BASE_STRUCT struct bluray_priv_s
static const m_option_t bluray_stream_opts_fields[] = { static const m_option_t bluray_stream_opts_fields[] = {
{ "hostname", ST_OFF(title), CONF_TYPE_INT, M_OPT_RANGE, 0, 99999, NULL}, OPT_INTRANGE("title", cfg_title, 0, 0, 99999),
{ "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL}, OPT_STRING("device", cfg_device, 0),
{ NULL, NULL, 0, 0, 0, 0, NULL } {0}
};
static const struct m_struct_st bluray_stream_opts = {
"bluray",
sizeof(struct stream_priv_s),
&bluray_stream_priv_dflts,
bluray_stream_opts_fields
}; };
static void bluray_stream_close(stream_t *s) static void bluray_stream_close(stream_t *s)
@@ -90,8 +85,6 @@ static void bluray_stream_close(stream_t *s)
struct bluray_priv_s *b = s->priv; struct bluray_priv_s *b = s->priv;
bd_close(b->bd); bd_close(b->bd);
b->bd = NULL;
free(b);
} }
static int bluray_stream_seek(stream_t *s, int64_t pos) static int bluray_stream_seek(stream_t *s, int64_t pos)
@@ -292,10 +285,9 @@ static int bluray_stream_control(stream_t *s, int cmd, void *arg)
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
static int bluray_stream_open(stream_t *s, int mode, void *opts) static int bluray_stream_open(stream_t *s, int mode)
{ {
struct stream_priv_s *p = opts; struct bluray_priv_s *b = s->priv;
struct bluray_priv_s *b;
BLURAY_TITLE_INFO *info = NULL; BLURAY_TITLE_INFO *info = NULL;
BLURAY *bd; BLURAY *bd;
@@ -310,8 +302,8 @@ static int bluray_stream_open(stream_t *s, int mode, void *opts)
int i; int i;
/* find the requested device */ /* find the requested device */
if (p->device) if (b->cfg_device)
device = p->device; device = b->cfg_device;
else if (bluray_device) else if (bluray_device)
device = bluray_device; device = bluray_device;
@@ -369,7 +361,7 @@ static int bluray_stream_open(stream_t *s, int mode, void *opts)
} }
/* Select current title */ /* Select current title */
title = p->title ? p->title - 1: title_guess; title = b->cfg_title ? b->cfg_title - 1: title_guess;
title = FFMIN(title, title_count - 1); title = FFMIN(title, title_count - 1);
bd_select_title(bd, title); bd_select_title(bd, title);
@@ -400,7 +392,6 @@ err_no_info:
s->close = bluray_stream_close; s->close = bluray_stream_close;
s->control = bluray_stream_control; s->control = bluray_stream_control;
b = calloc(1, sizeof(struct bluray_priv_s));
b->bd = bd; b->bd = bd;
b->current_angle = angle; b->current_angle = angle;
b->current_title = title; b->current_title = title;
@@ -409,7 +400,6 @@ err_no_info:
s->sector_size = BLURAY_SECTOR_SIZE; s->sector_size = BLURAY_SECTOR_SIZE;
s->flags = MP_STREAM_SEEK; s->flags = MP_STREAM_SEEK;
s->priv = b; s->priv = b;
s->url = strdup("br://");
mp_tmsg(MSGT_OPEN, MSGL_V, "Blu-ray successfully opened.\n"); mp_tmsg(MSGT_OPEN, MSGL_V, "Blu-ray successfully opened.\n");
@@ -420,6 +410,12 @@ const stream_info_t stream_info_bluray = {
"bd", "bd",
bluray_stream_open, bluray_stream_open,
{ "bd", "br", "bluray", NULL }, { "bd", "br", "bluray", NULL },
&bluray_stream_opts, .priv_defaults = &bluray_stream_priv_dflts,
1 .priv_size = sizeof(struct bluray_priv_s),
.options = bluray_stream_opts_fields,
.url_options = {
{"hostname", "title"},
{"filename", "device"},
{0}
},
}; };

View File

@@ -43,7 +43,6 @@
#include "stream.h" #include "stream.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/m_struct.h"
#include "libavutil/common.h" #include "libavutil/common.h"
#include "compat/mpbswap.h" #include "compat/mpbswap.h"
@@ -60,9 +59,8 @@ typedef struct {
int start_sector; int start_sector;
int end_sector; int end_sector;
cd_info_t *cd_info; cd_info_t *cd_info;
} cdda_priv;
static struct cdda_params { // options
int speed; int speed;
int paranoia_mode; int paranoia_mode;
char *generic_dev; char *generic_dev;
@@ -73,23 +71,19 @@ static struct cdda_params {
int no_skip; int no_skip;
char *device; char *device;
int span[2]; int span[2];
} cdda_dflts = { } cdda_priv;
static cdda_priv cdda_dflts = {
.search_overlap = -1, .search_overlap = -1,
}; };
#define ST_OFF(f) M_ST_OFF(struct cdda_params, f) #define OPT_BASE_STRUCT cdda_priv
static const m_option_t cdda_params_fields[] = { static const m_option_t cdda_params_fields[] = {
{"hostname", ST_OFF(span), CONF_TYPE_INT_PAIR, 0, 0, 0, NULL}, OPT_INTPAIR("span", span, 0),
{"port", ST_OFF(speed), CONF_TYPE_INT, M_OPT_RANGE, 1, 100, NULL}, OPT_INTRANGE("speed", speed, 0, 1, 100),
{"filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL}, OPT_STRING("device", device, 0),
{0} {0}
}; };
static const struct m_struct_st stream_opts = {
"cdda",
sizeof(struct cdda_params),
&cdda_dflts,
cdda_params_fields
};
/// We keep these options but now they set the defaults /// We keep these options but now they set the defaults
const m_option_t cdda_opts[] = { const m_option_t cdda_opts[] = {
@@ -319,20 +313,19 @@ static int control(stream_t *stream, int cmd, void *arg)
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
static int open_cdda(stream_t *st, int m, void *opts) static int open_cdda(stream_t *st, int m)
{ {
struct cdda_params *p = (struct cdda_params *)opts; cdda_priv *priv = st->priv;
cdda_priv *p = priv;
int mode = p->paranoia_mode; int mode = p->paranoia_mode;
int offset = p->toc_offset; int offset = p->toc_offset;
cdrom_drive_t *cdd = NULL; cdrom_drive_t *cdd = NULL;
cdda_priv *priv;
cd_info_t *cd_info; cd_info_t *cd_info;
unsigned int audiolen = 0; unsigned int audiolen = 0;
int last_track; int last_track;
int i; int i;
if (m != STREAM_READ) { if (m != STREAM_READ) {
m_struct_free(&stream_opts, opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
@@ -351,7 +344,6 @@ static int open_cdda(stream_t *st, int m, void *opts)
if (!cdd) { if (!cdd) {
mp_tmsg(MSGT_OPEN, MSGL_ERR, "Can't open CDDA device.\n"); mp_tmsg(MSGT_OPEN, MSGL_ERR, "Can't open CDDA device.\n");
m_struct_free(&stream_opts, opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
@@ -363,7 +355,6 @@ static int open_cdda(stream_t *st, int m, void *opts)
if (cdda_open(cdd) != 0) { if (cdda_open(cdd) != 0) {
mp_tmsg(MSGT_OPEN, MSGL_ERR, "Can't open disc.\n"); mp_tmsg(MSGT_OPEN, MSGL_ERR, "Can't open disc.\n");
cdda_close(cdd); cdda_close(cdd);
m_struct_free(&stream_opts, opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
@@ -424,7 +415,6 @@ static int open_cdda(stream_t *st, int m, void *opts)
cdda_close(cdd); cdda_close(cdd);
free(priv); free(priv);
cd_info_free(cd_info); cd_info_free(cd_info);
m_struct_free(&stream_opts, opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
@@ -465,8 +455,6 @@ static int open_cdda(stream_t *st, int m, void *opts)
st->demuxer = "rawaudio"; st->demuxer = "rawaudio";
m_struct_free(&stream_opts, opts);
print_cdtext(st, 0); print_cdtext(st, 0);
return STREAM_OK; return STREAM_OK;
@@ -476,6 +464,13 @@ const stream_info_t stream_info_cdda = {
"cdda", "cdda",
open_cdda, open_cdda,
{"cdda", NULL }, {"cdda", NULL },
&stream_opts, .priv_size = sizeof(cdda_priv),
.opts_url = 1, .priv_defaults = &cdda_dflts,
.options = cdda_params_fields,
.url_options = {
{"hostname", "span"},
{"port", "speed"},
{"filename", "device"},
{0}
},
}; };

View File

@@ -43,7 +43,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "stream.h" #include "stream.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/m_struct.h"
#include "core/path.h" #include "core/path.h"
#include "libavutil/avstring.h" #include "libavutil/avstring.h"
@@ -58,41 +57,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//TODO: CAMBIARE list_ptr e da globale a per_priv //TODO: CAMBIARE list_ptr e da globale a per_priv
static struct stream_priv_s static dvb_priv_t stream_defaults = {
{ .cfg_prog = "",
char *prog; .cfg_card = 1,
int card; .cfg_timeout = 30,
int timeout;
char *file;
}
stream_defaults =
{
"", 1, 30, NULL
}; };
#define ST_OFF(f) M_ST_OFF(struct stream_priv_s, f) #define OPT_BASE_STRUCT dvb_priv_t
/// URL definition /// URL definition
static const m_option_t stream_params[] = { static const m_option_t stream_params[] = {
{"hostname", ST_OFF(prog), CONF_TYPE_STRING, 0, 0, 0, NULL }, OPT_STRING("prog", cfg_prog, 0),
{"username", ST_OFF(card), CONF_TYPE_INT, M_OPT_RANGE, 1, 4, NULL}, OPT_INTRANGE("card", cfg_card, 0, 1, 4),
{NULL, NULL, 0, 0, 0, 0, NULL} {0}
}; };
static const struct m_struct_st stream_opts = {
"dvbin",
sizeof(struct stream_priv_s),
&stream_defaults,
stream_params
};
const m_option_t dvbin_opts_conf[] = { const m_option_t dvbin_opts_conf[] = {
{"prog", &stream_defaults.prog, CONF_TYPE_STRING, 0, 0 ,0, NULL}, {"prog", &stream_defaults.cfg_prog, CONF_TYPE_STRING, 0, 0 ,0, NULL},
{"card", &stream_defaults.card, CONF_TYPE_INT, M_OPT_RANGE, 1, 4, NULL}, {"card", &stream_defaults.cfg_card, CONF_TYPE_INT, M_OPT_RANGE, 1, 4, NULL},
{"timeout", &stream_defaults.timeout, CONF_TYPE_INT, M_OPT_RANGE, 1, 30, NULL}, {"timeout", &stream_defaults.cfg_timeout, CONF_TYPE_INT, M_OPT_RANGE, 1, 30, NULL},
{"file", &stream_defaults.file, CONF_TYPE_STRING, 0, 0 ,0, NULL},
{NULL, NULL, 0, 0, 0, 0, NULL} {NULL, NULL, 0, 0, 0, 0, NULL}
}; };
@@ -540,7 +523,7 @@ int dvb_set_channel(stream_t *stream, int card, int n)
if(channel->freq != priv->last_freq) if(channel->freq != priv->last_freq)
if (! dvb_tune(priv, channel->freq, channel->pol, channel->srate, channel->diseqc, channel->tone, if (! dvb_tune(priv, channel->freq, channel->pol, channel->srate, channel->diseqc, channel->tone,
channel->inv, channel->mod, channel->gi, channel->trans, channel->bw, channel->cr, channel->cr_lp, channel->hier, priv->timeout)) channel->inv, channel->mod, channel->gi, channel->trans, channel->bw, channel->cr, channel->cr_lp, channel->hier, priv->cfg_timeout))
return 0; return 0;
priv->last_freq = channel->freq; priv->last_freq = channel->freq;
@@ -608,14 +591,15 @@ static void dvbin_close(stream_t *stream)
} }
static int dvb_streaming_start(stream_t *stream, struct stream_priv_s *opts, int tuner_type, char *progname) static int dvb_streaming_start(stream_t *stream, int tuner_type, char *progname)
{ {
int i; int i;
dvb_channel_t *channel = NULL; dvb_channel_t *channel = NULL;
dvb_priv_t *priv = stream->priv; dvb_priv_t *priv = stream->priv;
dvb_priv_t *opts = priv;
mp_msg(MSGT_DEMUX, MSGL_V, "\r\ndvb_streaming_start(PROG: %s, CARD: %d, FILE: %s)\r\n", mp_msg(MSGT_DEMUX, MSGL_V, "\r\ndvb_streaming_start(PROG: %s, CARD: %d)\r\n",
opts->prog, opts->card, opts->file); opts->cfg_prog, opts->cfg_card);
priv->is_on = 0; priv->is_on = 0;
@@ -655,12 +639,12 @@ static int dvb_streaming_start(stream_t *stream, struct stream_priv_s *opts, int
static int dvb_open(stream_t *stream, int mode, void *opts) static int dvb_open(stream_t *stream, int mode)
{ {
// I don't force the file format bacause, although it's almost always TS, // I don't force the file format bacause, although it's almost always TS,
// there are some providers that stream an IP multicast with M$ Mpeg4 inside // there are some providers that stream an IP multicast with M$ Mpeg4 inside
struct stream_priv_s* p = (struct stream_priv_s*)opts; dvb_priv_t *priv = stream->priv;
dvb_priv_t *priv; dvb_priv_t *p = priv;
char *progname; char *progname;
int tuner_type = 0, i; int tuner_type = 0, i;
@@ -668,11 +652,6 @@ static int dvb_open(stream_t *stream, int mode, void *opts)
if(mode != STREAM_READ) if(mode != STREAM_READ)
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
stream->priv = calloc(1, sizeof(dvb_priv_t));
if(stream->priv == NULL)
return STREAM_ERROR;
priv = (dvb_priv_t *)stream->priv;
priv->fe_fd = priv->sec_fd = priv->dvr_fd = -1; priv->fe_fd = priv->sec_fd = priv->dvr_fd = -1;
priv->config = dvb_get_config(); priv->config = dvb_get_config();
if(priv->config == NULL) if(priv->config == NULL)
@@ -685,7 +664,7 @@ static int dvb_open(stream_t *stream, int mode, void *opts)
priv->card = -1; priv->card = -1;
for(i=0; i<priv->config->count; i++) for(i=0; i<priv->config->count; i++)
{ {
if(priv->config->cards[i].devno+1 == p->card) if(priv->config->cards[i].devno+1 == p->cfg_card)
{ {
priv->card = i; priv->card = i;
break; break;
@@ -695,10 +674,10 @@ static int dvb_open(stream_t *stream, int mode, void *opts)
if(priv->card == -1) if(priv->card == -1)
{ {
free(priv); free(priv);
mp_msg(MSGT_DEMUX, MSGL_ERR, "NO CONFIGURATION FOUND FOR CARD N. %d, exit\n", p->card); mp_msg(MSGT_DEMUX, MSGL_ERR, "NO CONFIGURATION FOUND FOR CARD N. %d, exit\n", p->cfg_card);
return STREAM_ERROR; return STREAM_ERROR;
} }
priv->timeout = p->timeout; priv->timeout = p->cfg_timeout;
tuner_type = priv->config->cards[priv->card].type; tuner_type = priv->config->cards[priv->card].type;
@@ -713,17 +692,17 @@ static int dvb_open(stream_t *stream, int mode, void *opts)
priv->tuner_type = tuner_type; priv->tuner_type = tuner_type;
mp_msg(MSGT_DEMUX, MSGL_V, "OPEN_DVB: prog=%s, card=%d, type=%d\n", mp_msg(MSGT_DEMUX, MSGL_V, "OPEN_DVB: prog=%s, card=%d, type=%d\n",
p->prog, priv->card+1, priv->tuner_type); p->cfg_prog, priv->card+1, priv->tuner_type);
priv->list = priv->config->cards[priv->card].list; priv->list = priv->config->cards[priv->card].list;
if((! strcmp(p->prog, "")) && (priv->list != NULL)) if((! strcmp(p->cfg_prog, "")) && (priv->list != NULL))
progname = priv->list->channels[0].name; progname = priv->list->channels[0].name;
else else
progname = p->prog; progname = p->cfg_prog;
if(! dvb_streaming_start(stream, p, tuner_type, progname)) if(! dvb_streaming_start(stream, tuner_type, progname))
{ {
free(stream->priv); free(stream->priv);
stream->priv = NULL; stream->priv = NULL;
@@ -733,7 +712,6 @@ static int dvb_open(stream_t *stream, int mode, void *opts)
stream->type = STREAMTYPE_DVB; stream->type = STREAMTYPE_DVB;
stream->fill_buffer = dvb_streaming_read; stream->fill_buffer = dvb_streaming_read;
stream->close = dvbin_close; stream->close = dvbin_close;
m_struct_free(&stream_opts, opts);
stream->demuxer = "lavf"; stream->demuxer = "lavf";
stream->lavf_type = "mpegts"; stream->lavf_type = "mpegts";
@@ -855,6 +833,12 @@ const stream_info_t stream_info_dvb = {
"dvbin", "dvbin",
dvb_open, dvb_open,
{ "dvb", NULL }, { "dvb", NULL },
&stream_opts, .priv_size = sizeof(dvb_priv_t),
1 // Urls are an option string .priv_defaults = &stream_defaults,
.options = stream_params,
.url_options = {
{"hostname", "prog"},
{"username", "card"},
{0}
},
}; };

View File

@@ -39,7 +39,6 @@
#include "stream.h" #include "stream.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/m_struct.h"
#include "stream_dvd.h" #include "stream_dvd.h"
#include "stream_dvd_common.h" #include "stream_dvd_common.h"
@@ -64,26 +63,16 @@ int dvd_angle=1;
#endif #endif
static struct stream_priv_s { static const dvd_priv_t stream_priv_dflts = {
int title; .cfg_title = 1,
char* device;
} stream_priv_dflts = {
1,
NULL
}; };
#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f) #define OPT_BASE_STRUCT dvd_priv_t
/// URL definition /// URL definition
static const m_option_t stream_opts_fields[] = { static const m_option_t stream_opts_fields[] = {
{ "hostname", ST_OFF(title), CONF_TYPE_INT, M_OPT_RANGE, 1, 99, NULL}, OPT_INTRANGE("title", cfg_title, 0, 1, 99),
{ "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL}, OPT_STRING("device", cfg_device, 0),
{ NULL, NULL, 0, 0, 0, 0, NULL } {0}
};
static const struct m_struct_st stream_opts = {
"dvd",
sizeof(struct stream_priv_s),
&stream_priv_dflts,
stream_opts_fields
}; };
int dvd_chapter_from_cell(dvd_priv_t* dvd,int title,int cell) int dvd_chapter_from_cell(dvd_priv_t* dvd,int title,int cell)
@@ -747,16 +736,15 @@ static int control(stream_t *stream,int cmd,void* arg)
} }
static int open_s(stream_t *stream,int mode, void* opts) static int open_s(stream_t *stream, int mode)
{ {
struct stream_priv_s* p = (struct stream_priv_s*)opts;
int k; int k;
dvd_priv_t *d = stream->priv;
mp_msg(MSGT_OPEN,MSGL_V,"URL: %s\n", stream->url); mp_msg(MSGT_OPEN,MSGL_V,"URL: %s\n", stream->url);
dvd_title = p->title; dvd_title = d->cfg_title;
if(1){ if(1){
//int ret,ret2; //int ret,ret2;
dvd_priv_t *d;
int ttn,pgc_id,pgn; int ttn,pgc_id,pgn;
dvd_reader_t *dvd; dvd_reader_t *dvd;
dvd_file_t *title; dvd_file_t *title;
@@ -767,8 +755,8 @@ static int open_s(stream_t *stream,int mode, void* opts)
/** /**
* Open the disc. * Open the disc.
*/ */
if(p->device) if(d->cfg_device)
dvd_device_current = p->device; dvd_device_current = d->cfg_device;
else if(dvd_device) else if(dvd_device)
dvd_device_current = dvd_device; dvd_device_current = dvd_device;
else else
@@ -802,7 +790,6 @@ static int open_s(stream_t *stream,int mode, void* opts)
free(temp_device); free(temp_device);
if(!dvd) { if(!dvd) {
m_struct_free(&stream_opts,opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
} else } else
@@ -811,7 +798,6 @@ static int open_s(stream_t *stream,int mode, void* opts)
dvd = DVDOpen(dvd_device_current); dvd = DVDOpen(dvd_device_current);
if(!dvd) { if(!dvd) {
mp_tmsg(MSGT_OPEN,MSGL_ERR,"Couldn't open DVD device: %s (%s)\n",dvd_device_current, strerror(errno)); mp_tmsg(MSGT_OPEN,MSGL_ERR,"Couldn't open DVD device: %s (%s)\n",dvd_device_current, strerror(errno));
m_struct_free(&stream_opts,opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
} }
@@ -826,7 +812,6 @@ static int open_s(stream_t *stream,int mode, void* opts)
if(!vmg_file) { if(!vmg_file) {
mp_tmsg(MSGT_OPEN,MSGL_ERR, "Can't open VMG info!\n"); mp_tmsg(MSGT_OPEN,MSGL_ERR, "Can't open VMG info!\n");
DVDClose( dvd ); DVDClose( dvd );
m_struct_free(&stream_opts,opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
tt_srpt = vmg_file->tt_srpt; tt_srpt = vmg_file->tt_srpt;
@@ -866,7 +851,6 @@ static int open_s(stream_t *stream,int mode, void* opts)
mp_tmsg(MSGT_OPEN,MSGL_ERR, "Invalid DVD title number: %d\n", dvd_title); mp_tmsg(MSGT_OPEN,MSGL_ERR, "Invalid DVD title number: %d\n", dvd_title);
ifoClose( vmg_file ); ifoClose( vmg_file );
DVDClose( dvd ); DVDClose( dvd );
m_struct_free(&stream_opts,opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_CURRENT_TITLE=%d\n", dvd_title); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_CURRENT_TITLE=%d\n", dvd_title);
@@ -901,7 +885,6 @@ static int open_s(stream_t *stream,int mode, void* opts)
mp_msg(MSGT_OPEN,MSGL_V, "DVD successfully opened.\n"); mp_msg(MSGT_OPEN,MSGL_V, "DVD successfully opened.\n");
// store data // store data
d=malloc(sizeof(dvd_priv_t)); memset(d,0,sizeof(dvd_priv_t));
d->dvd=dvd; d->dvd=dvd;
d->title=title; d->title=title;
d->vmg_file=vmg_file; d->vmg_file=vmg_file;
@@ -1054,54 +1037,58 @@ static int open_s(stream_t *stream,int mode, void* opts)
fail: fail:
ifoClose(vmg_file); ifoClose(vmg_file);
DVDClose(dvd); DVDClose(dvd);
m_struct_free(&stream_opts, opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
mp_tmsg(MSGT_DVD,MSGL_ERR,"mpv was compiled without DVD support, exiting.\n"); mp_tmsg(MSGT_DVD,MSGL_ERR,"mpv was compiled without DVD support, exiting.\n");
m_struct_free(&stream_opts,opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
static int ifo_stream_open (stream_t *stream, int mode, void *opts) static int ifo_stream_open (stream_t *stream, int mode)
{ {
char* filename; char* filename;
struct stream_priv_s *spriv; dvd_priv_t *priv = talloc_ptrtype(stream, priv);
int len = strlen(stream->url); stream->priv = priv;
*priv = stream_priv_dflts;
if (len < 4 || strcasecmp (stream->url + len - 4, ".ifo")) int len = strlen(stream->path);
if (len < 4 || strcasecmp (stream->path + len - 4, ".ifo"))
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
mp_msg(MSGT_DVD, MSGL_INFO, ".IFO detected. Redirecting to dvd://\n"); mp_msg(MSGT_DVD, MSGL_INFO, ".IFO detected. Redirecting to dvd://\n");
filename = strdup(basename(stream->url)); filename = strdup(basename(stream->path));
spriv=calloc(1, sizeof(struct stream_priv_s)); talloc_free(priv->cfg_device);
spriv->device = strdup(dirname(stream->url)); priv->cfg_device = talloc_strdup(NULL, dirname(stream->path));
if(!strncasecmp(filename,"vts_",4)) if(!strncasecmp(filename,"vts_",4))
{ {
if(sscanf(filename+3, "_%02d_", &spriv->title)!=1) if(sscanf(filename+3, "_%02d_", &priv->cfg_title)!=1)
spriv->title=1; priv->cfg_title = 1;
}else }else
spriv->title=1; priv->cfg_title = 1;
free(filename); free(filename);
stream->url=talloc_strdup(stream, "dvd://"); stream->url=talloc_strdup(stream, "dvd://");
return open_s(stream, mode, spriv); return open_s(stream, mode);
} }
const stream_info_t stream_info_dvd = { const stream_info_t stream_info_dvd = {
"dvd", "dvd",
open_s, open_s,
{ "dvd", NULL }, { "dvd", NULL },
&stream_opts, .priv_size = sizeof(dvd_priv_t),
1 // Urls are an option string .priv_defaults = &stream_priv_dflts,
.options = stream_opts_fields,
.url_options = {
{"hostname", "title"},
{"filename", "device"},
{0}
},
}; };
const stream_info_t stream_info_ifo = { const stream_info_t stream_info_ifo = {
"ifo", "ifo",
ifo_stream_open, ifo_stream_open,
{ "file", "", NULL }, { "file", "", NULL },
NULL,
0
}; };

View File

@@ -54,6 +54,9 @@ typedef struct {
// subtitles // subtitles
int nr_of_subtitles; int nr_of_subtitles;
stream_language_t subtitles[32]; stream_language_t subtitles[32];
int cfg_title;
char *cfg_device;
} dvd_priv_t; } dvd_priv_t;
int dvd_number_of_subs(stream_t *stream); int dvd_number_of_subs(stream_t *stream);

View File

@@ -32,34 +32,12 @@
#include "core/mp_msg.h" #include "core/mp_msg.h"
#include "stream.h" #include "stream.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/m_struct.h"
struct priv { struct priv {
int fd; int fd;
bool close; bool close;
}; };
static struct stream_priv_s {
char* filename;
char *filename2;
} stream_priv_dflts = {
NULL, NULL
};
#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
/// URL definition
static const m_option_t stream_opts_fields[] = {
{"string", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL},
{"filename", ST_OFF(filename2), CONF_TYPE_STRING, 0, 0 ,0, NULL},
{ NULL, NULL, 0, 0, 0, 0, NULL }
};
static const struct m_struct_st stream_opts = {
"file",
sizeof(struct stream_priv_s),
&stream_priv_dflts,
stream_opts_fields
};
static int fill_buffer(stream_t *s, char* buffer, int max_len){ static int fill_buffer(stream_t *s, char* buffer, int max_len){
struct priv *p = s->priv; struct priv *p = s->priv;
int r = read(p->fd,buffer,max_len); int r = read(p->fd,buffer,max_len);
@@ -128,13 +106,12 @@ static void s_close(stream_t *s)
close(p->fd); close(p->fd);
} }
static int open_f(stream_t *stream,int mode, void* opts) static int open_f(stream_t *stream, int mode)
{ {
int f; int f;
mode_t m = 0; mode_t m = 0;
int64_t len; int64_t len;
unsigned char *filename; char *filename = stream->path;
struct stream_priv_s* p = (struct stream_priv_s*)opts;
struct priv *priv = talloc_ptrtype(stream, priv); struct priv *priv = talloc_ptrtype(stream, priv);
*priv = (struct priv) { .fd = -1 }; *priv = (struct priv) { .fd = -1 };
stream->priv = priv; stream->priv = priv;
@@ -145,22 +122,9 @@ static int open_f(stream_t *stream,int mode, void* opts)
m = O_RDWR|O_CREAT|O_TRUNC; m = O_RDWR|O_CREAT|O_TRUNC;
else { else {
mp_msg(MSGT_OPEN,MSGL_ERR, "[file] Unknown open mode %d\n",mode); mp_msg(MSGT_OPEN,MSGL_ERR, "[file] Unknown open mode %d\n",mode);
m_struct_free(&stream_opts,opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
if(p->filename)
filename = p->filename;
else if(p->filename2)
filename = p->filename2;
else
filename = NULL;
if(!filename) {
mp_msg(MSGT_OPEN,MSGL_ERR, "[file] No filename\n");
m_struct_free(&stream_opts,opts);
return STREAM_ERROR;
}
#if HAVE_DOS_PATHS #if HAVE_DOS_PATHS
// extract '/' from '/x:/path' // extract '/' from '/x:/path'
if( filename[ 0 ] == '/' && filename[ 1 ] && filename[ 2 ] == ':' ) if( filename[ 0 ] == '/' && filename[ 1 ] && filename[ 2 ] == ':' )
@@ -195,7 +159,6 @@ static int open_f(stream_t *stream,int mode, void* opts)
if(f<0) { if(f<0) {
mp_tmsg(MSGT_OPEN, MSGL_ERR, "Cannot open file '%s': %s\n", filename, mp_tmsg(MSGT_OPEN, MSGL_ERR, "Cannot open file '%s': %s\n", filename,
strerror(errno)); strerror(errno));
m_struct_free(&stream_opts,opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
#ifndef __MINGW32__ #ifndef __MINGW32__
@@ -203,7 +166,6 @@ static int open_f(stream_t *stream,int mode, void* opts)
if (fstat(f, &st) == 0 && S_ISDIR(st.st_mode)) { if (fstat(f, &st) == 0 && S_ISDIR(st.st_mode)) {
mp_tmsg(MSGT_OPEN,MSGL_ERR,"File is a directory: '%s'\n",filename); mp_tmsg(MSGT_OPEN,MSGL_ERR,"File is a directory: '%s'\n",filename);
close(f); close(f);
m_struct_free(&stream_opts,opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
#endif #endif
@@ -234,7 +196,6 @@ static int open_f(stream_t *stream,int mode, void* opts)
stream->read_chunk = 64*1024; stream->read_chunk = 64*1024;
stream->close = s_close; stream->close = s_close;
m_struct_free(&stream_opts,opts);
return STREAM_OK; return STREAM_OK;
} }
@@ -242,6 +203,4 @@ const stream_info_t stream_info_file = {
"file", "file",
open_f, open_f,
{ "file", "", NULL }, { "file", "", NULL },
&stream_opts,
1 // Urls are an option string
}; };

View File

@@ -25,14 +25,13 @@
#include "core/mp_msg.h" #include "core/mp_msg.h"
#include "stream.h" #include "stream.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/m_struct.h"
#include "cookies.h" #include "cookies.h"
#include "core/bstr.h" #include "core/bstr.h"
#include "core/mp_talloc.h" #include "core/mp_talloc.h"
static int open_f(stream_t *stream, int mode, void *opts); static int open_f(stream_t *stream, int mode);
static char **read_icy(stream_t *stream); static char **read_icy(stream_t *stream);
static int fill_buffer(stream_t *s, char *buffer, int max_len) static int fill_buffer(stream_t *s, char *buffer, int max_len)
@@ -114,7 +113,7 @@ static int control(stream_t *s, int cmd, void *arg)
// avio doesn't seem to support this - emulate it by reopening // avio doesn't seem to support this - emulate it by reopening
close_f(s); close_f(s);
s->priv = NULL; s->priv = NULL;
return open_f(s, STREAM_READ, NULL); return open_f(s, STREAM_READ);
} }
} }
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
@@ -131,7 +130,7 @@ static bool mp_avio_has_opts(AVIOContext *avio)
static const char * const prefix[] = { "lavf://", "ffmpeg://" }; static const char * const prefix[] = { "lavf://", "ffmpeg://" };
static int open_f(stream_t *stream, int mode, void *opts) static int open_f(stream_t *stream, int mode)
{ {
int flags = 0; int flags = 0;
AVIOContext *avio = NULL; AVIOContext *avio = NULL;
@@ -309,6 +308,4 @@ const stream_info_t stream_info_ffmpeg = {
open_f, open_f,
{ "lavf", "ffmpeg", "rtmp", "rtsp", "http", "https", "mms", "mmst", "mmsh", { "lavf", "ffmpeg", "rtmp", "rtsp", "http", "https", "mms", "mmst", "mmsh",
"mmshttp", "udp", "ftp", "rtp", "httpproxy", NULL }, "mmshttp", "udp", "ftp", "rtp", "httpproxy", NULL },
NULL,
1 // Urls are an option string
}; };

View File

@@ -54,7 +54,7 @@ static int control(stream_t *s, int cmd, void *arg)
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
static int open_f(stream_t *stream, int mode, void* opts) static int open_f(stream_t *stream, int mode)
{ {
stream->fill_buffer = fill_buffer; stream->fill_buffer = fill_buffer;
stream->seek = seek; stream->seek = seek;

View File

@@ -29,7 +29,7 @@
#include "stream.h" #include "stream.h"
static int static int
mf_stream_open (stream_t *stream, int mode, void *opts) mf_stream_open (stream_t *stream, int mode)
{ {
stream->type = STREAMTYPE_MF; stream->type = STREAMTYPE_MF;
stream->demuxer = "mf"; stream->demuxer = "mf";
@@ -41,6 +41,4 @@ const stream_info_t stream_info_mf = {
"mf", "mf",
mf_stream_open, mf_stream_open,
{ "mf", NULL }, { "mf", NULL },
NULL,
1
}; };

View File

@@ -25,7 +25,7 @@
#include "stream.h" #include "stream.h"
static int open_s(stream_t *stream,int mode, void* opts) static int open_s(stream_t *stream,int mode)
{ {
return 1; return 1;
} }
@@ -35,6 +35,4 @@ const stream_info_t stream_info_null = {
"null", "null",
open_s, open_s,
{ "null", NULL }, { "null", NULL },
NULL,
0 // Urls are an option string
}; };

View File

@@ -1556,7 +1556,7 @@ pvr_stream_read (stream_t *stream, char *buffer, int size)
} }
static int static int
pvr_stream_open (stream_t *stream, int mode, void *opts) pvr_stream_open (stream_t *stream, int mode)
{ {
struct v4l2_capability vcap; struct v4l2_capability vcap;
struct v4l2_ext_controls ctrls; struct v4l2_ext_controls ctrls;
@@ -1760,6 +1760,4 @@ const stream_info_t stream_info_pvr = {
"pvr", "pvr",
pvr_stream_open, pvr_stream_open,
{ "pvr", NULL }, { "pvr", NULL },
NULL,
1
}; };

View File

@@ -43,7 +43,6 @@
#include "stream.h" #include "stream.h"
#include "demux/demux.h" #include "demux/demux.h"
#include "core/m_struct.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/mp_msg.h" #include "core/mp_msg.h"
#include "stream_radio.h" #include "stream_radio.h"
@@ -118,18 +117,11 @@ typedef struct radio_driver_s {
int (*get_frequency)(radio_priv_t* priv,float* frequency); int (*get_frequency)(radio_priv_t* priv,float* frequency);
} radio_driver_t; } radio_driver_t;
#define ST_OFF(f) M_ST_OFF(radio_param_t,f) #define OPT_BASE_STRUCT radio_param_t
static const m_option_t stream_opts_fields[] = { static const m_option_t stream_opts_fields[] = {
{"hostname", ST_OFF(freq_channel), CONF_TYPE_FLOAT, 0, 0 ,0, NULL}, OPT_FLOAT("title", freq_channel, 0),
{"filename", ST_OFF(capture), CONF_TYPE_STRING, 0, 0 ,0, NULL}, OPT_STRING("device", capture, 0),
{ NULL, NULL, 0, 0, 0, 0, NULL } {0}
};
static const struct m_struct_st stream_opts = {
"radio",
sizeof(radio_param_t),
&stream_radio_defaults,
stream_opts_fields
}; };
static void close_s(struct stream *stream); static void close_s(struct stream *stream);
@@ -824,7 +816,7 @@ static const radio_driver_t* radio_drivers[]={
* Stream initialization * Stream initialization
* \return STREAM_OK if success, STREAM_ERROR otherwise * \return STREAM_OK if success, STREAM_ERROR otherwise
*/ */
static int open_s(stream_t *stream,int mode, void* opts) static int open_s(stream_t *stream,int mode)
{ {
radio_priv_t* priv; radio_priv_t* priv;
float frequency=0; float frequency=0;
@@ -842,7 +834,8 @@ static int open_s(stream_t *stream,int mode, void* opts)
return STREAM_ERROR; return STREAM_ERROR;
priv->radio_param=opts; priv->radio_param=stream->priv;
stream->priv=NULL;
#ifdef CONFIG_RADIO_CAPTURE #ifdef CONFIG_RADIO_CAPTURE
if (priv->radio_param->capture && strncmp("capture",priv->radio_param->capture,7)==0) if (priv->radio_param->capture && strncmp("capture",priv->radio_param->capture,7)==0)
@@ -961,8 +954,6 @@ static void close_s(struct stream *stream){
close(priv->radio_fd); close(priv->radio_fd);
} }
if(priv->radio_param)
m_struct_free(&stream_opts,priv->radio_param);
free(priv); free(priv);
stream->priv=NULL; stream->priv=NULL;
} }
@@ -971,6 +962,12 @@ const stream_info_t stream_info_radio = {
"radio", "radio",
open_s, open_s,
{ "radio", NULL }, { "radio", NULL },
&stream_opts, .priv_size = sizeof(radio_param_t),
1 // Urls are an option string .priv_defaults = &stream_radio_defaults,
.options = stream_opts_fields,
.url_options = {
{"hostname", "freqchannel"},
{"username", "capture"},
{0}
},
}; };

View File

@@ -26,29 +26,11 @@
#include "core/mp_msg.h" #include "core/mp_msg.h"
#include "stream.h" #include "stream.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/m_struct.h"
struct priv { struct priv {
int fd; int fd;
}; };
static struct stream_priv_s {
} stream_priv_dflts = {
};
#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
// URL definition
static const m_option_t stream_opts_fields[] = {
{ NULL, NULL, 0, 0, 0, 0, NULL }
};
static const struct m_struct_st stream_opts = {
"smb",
sizeof(struct stream_priv_s),
&stream_priv_dflts,
stream_opts_fields
};
static char smb_password[15]; static char smb_password[15];
static char smb_username[15]; static char smb_username[15];
@@ -126,7 +108,7 @@ static void close_f(stream_t *s){
smbc_close(p->fd); smbc_close(p->fd);
} }
static int open_f (stream_t *stream, int mode, void *opts) static int open_f (stream_t *stream, int mode)
{ {
char *filename; char *filename;
mode_t m = 0; mode_t m = 0;
@@ -144,27 +126,23 @@ static int open_f (stream_t *stream, int mode, void *opts)
m = O_RDWR|O_CREAT|O_TRUNC; m = O_RDWR|O_CREAT|O_TRUNC;
else { else {
mp_msg(MSGT_OPEN, MSGL_ERR, "[smb] Unknown open mode %d\n", mode); mp_msg(MSGT_OPEN, MSGL_ERR, "[smb] Unknown open mode %d\n", mode);
m_struct_free (&stream_opts, opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
if(!filename) { if(!filename) {
mp_msg(MSGT_OPEN,MSGL_ERR, "[smb] Bad url\n"); mp_msg(MSGT_OPEN,MSGL_ERR, "[smb] Bad url\n");
m_struct_free(&stream_opts, opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
err = smbc_init(smb_auth_fn, 1); err = smbc_init(smb_auth_fn, 1);
if (err < 0) { if (err < 0) {
mp_tmsg(MSGT_OPEN,MSGL_ERR,"Cannot init the libsmbclient library: %d\n",err); mp_tmsg(MSGT_OPEN,MSGL_ERR,"Cannot init the libsmbclient library: %d\n",err);
m_struct_free(&stream_opts, opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
fd = smbc_open(filename, m,0644); fd = smbc_open(filename, m,0644);
if (fd < 0) { if (fd < 0) {
mp_tmsg(MSGT_OPEN,MSGL_ERR,"Could not open from LAN: '%s'\n", filename); mp_tmsg(MSGT_OPEN,MSGL_ERR,"Could not open from LAN: '%s'\n", filename);
m_struct_free(&stream_opts, opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
@@ -185,7 +163,6 @@ static int open_f (stream_t *stream, int mode, void *opts)
stream->close = close_f; stream->close = close_f;
stream->control = control; stream->control = control;
m_struct_free(&stream_opts, opts);
return STREAM_OK; return STREAM_OK;
} }
@@ -193,6 +170,4 @@ const stream_info_t stream_info_smb = {
"smb", "smb",
open_f, open_f,
{"smb", NULL}, {"smb", NULL},
&stream_opts,
0 //Url is an option string
}; };

View File

@@ -28,7 +28,6 @@
#include "stream.h" #include "stream.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/m_struct.h"
#include "tv.h" #include "tv.h"
#include <stdio.h> #include <stdio.h>
@@ -75,33 +74,22 @@ tv_param_t stream_tv_defaults = {
0.5, //scan_period 0.5, //scan_period
}; };
#define ST_OFF(f) M_ST_OFF(tv_param_t,f) #define OPT_BASE_STRUCT tv_param_t
static const m_option_t stream_opts_fields[] = { static const m_option_t stream_opts_fields[] = {
{"hostname", ST_OFF(channel), CONF_TYPE_STRING, 0, 0 ,0, NULL}, OPT_STRING("channel", channel, 0),
{"filename", ST_OFF(input), CONF_TYPE_INT, 0, 0 ,0, NULL}, OPT_INT("input", input, 0),
{ NULL, NULL, 0, 0, 0, 0, NULL } {0}
};
static const struct m_struct_st stream_opts = {
"tv",
sizeof(tv_param_t),
&stream_tv_defaults,
stream_opts_fields
}; };
static void static void
tv_stream_close (stream_t *stream) tv_stream_close (stream_t *stream)
{ {
if(stream->priv)
m_struct_free(&stream_opts,stream->priv);
stream->priv=NULL;
} }
static int static int
tv_stream_open (stream_t *stream, int mode, void *opts) tv_stream_open (stream_t *stream, int mode)
{ {
stream->type = STREAMTYPE_TV; stream->type = STREAMTYPE_TV;
stream->priv = opts;
stream->close=tv_stream_close; stream->close=tv_stream_close;
stream->demuxer = "tv"; stream->demuxer = "tv";
@@ -112,6 +100,12 @@ const stream_info_t stream_info_tv = {
"tv", "tv",
tv_stream_open, tv_stream_open,
{ "tv", NULL }, { "tv", NULL },
&stream_opts, .priv_size = sizeof(tv_param_t),
1 .priv_defaults = &stream_tv_defaults,
.options = stream_opts_fields,
.url_options = {
{"hostname", "channel"},
{"filename", "input"},
{0}
},
}; };

View File

@@ -27,7 +27,6 @@
#include "core/mp_msg.h" #include "core/mp_msg.h"
#include "stream.h" #include "stream.h"
#include "core/m_option.h" #include "core/m_option.h"
#include "core/m_struct.h"
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
@@ -59,28 +58,6 @@
extern char *cdrom_device; extern char *cdrom_device;
static struct stream_priv_s {
int track;
char* device;
} stream_priv_dflts = {
1,
NULL
};
#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
/// URL definition
static const m_option_t stream_opts_fields[] = {
{ "hostname", ST_OFF(track), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL },
{ "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL},
{ NULL, NULL, 0, 0, 0, 0, NULL }
};
static const struct m_struct_st stream_opts = {
"vcd",
sizeof(struct stream_priv_s),
&stream_priv_dflts,
stream_opts_fields
};
static int fill_buffer(stream_t *s, char* buffer, int max_len){ static int fill_buffer(stream_t *s, char* buffer, int max_len){
if(s->pos > s->end_pos) /// don't past end of current track if(s->pos > s->end_pos) /// don't past end of current track
return 0; return 0;
@@ -100,9 +77,8 @@ static void close_s(stream_t *stream) {
free(stream->priv); free(stream->priv);
} }
static int open_s(stream_t *stream,int mode, void* opts) static int open_s(stream_t *stream,int mode)
{ {
struct stream_priv_s* p = opts;
int ret,ret2,f,sect,tmp; int ret,ret2,f,sect,tmp;
mp_vcd_priv_t* vcd; mp_vcd_priv_t* vcd;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -110,7 +86,7 @@ static int open_s(stream_t *stream,int mode, void* opts)
#endif #endif
#if defined(__MINGW32__) || defined(__CYGWIN__) #if defined(__MINGW32__) || defined(__CYGWIN__)
HANDLE hd; HANDLE hd;
char device[] = "\\\\.\\?:"; char device[20] = "\\\\.\\?:";
#endif #endif
if(mode != STREAM_READ if(mode != STREAM_READ
@@ -118,29 +94,31 @@ static int open_s(stream_t *stream,int mode, void* opts)
|| GetVersion() > 0x80000000 // Win9x || GetVersion() > 0x80000000 // Win9x
#endif #endif
) { ) {
m_struct_free(&stream_opts,opts);
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
} }
if (!p->device) { char *dev = stream->url;
if (strncmp("vcd://", dev, 6) != 0)
return STREAM_UNSUPPORTED;
dev += 6;
if (!dev[0]) {
if(cdrom_device) if(cdrom_device)
p->device = talloc_strdup(NULL, cdrom_device); dev = cdrom_device;
else else
p->device = talloc_strdup(NULL, DEFAULT_CDROM_DEVICE); dev = DEFAULT_CDROM_DEVICE;
} }
#if defined(__MINGW32__) || defined(__CYGWIN__) #if defined(__MINGW32__) || defined(__CYGWIN__)
device[4] = p->device[0]; device[4] = dev ? dev[0] : 0;
/* open() can't be used for devices so do it the complicated way */ /* open() can't be used for devices so do it the complicated way */
hd = CreateFile(device, GENERIC_READ, FILE_SHARE_READ, NULL, hd = CreateFile(device, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
f = _open_osfhandle((intptr_t)hd, _O_RDONLY); f = _open_osfhandle((intptr_t)hd, _O_RDONLY);
#else #else
f=open(p->device,O_RDONLY); f=open(dev,O_RDONLY);
#endif #endif
if(f<0){ if(f<0){
mp_tmsg(MSGT_OPEN,MSGL_ERR,"CD-ROM Device '%s' not found.\n",p->device); mp_tmsg(MSGT_OPEN,MSGL_ERR,"CD-ROM Device '%s' not found.\n",dev);
m_struct_free(&stream_opts,opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
@@ -148,25 +126,22 @@ static int open_s(stream_t *stream,int mode, void* opts)
if(!vcd) { if(!vcd) {
mp_msg(MSGT_OPEN,MSGL_ERR,"Failed to get cd toc\n"); mp_msg(MSGT_OPEN,MSGL_ERR,"Failed to get cd toc\n");
close(f); close(f);
m_struct_free(&stream_opts,opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
ret2=vcd_get_track_end(vcd,p->track); ret2=vcd_get_track_end(vcd,1);
if(ret2<0){ if(ret2<0){
mp_msg(MSGT_OPEN, MSGL_ERR, "%s (get)\n", mp_msg(MSGT_OPEN, MSGL_ERR, "%s (get)\n",
mp_gtext("Error selecting VCD track.")); mp_gtext("Error selecting VCD track."));
close(f); close(f);
free(vcd); free(vcd);
m_struct_free(&stream_opts,opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
ret=vcd_seek_to_track(vcd,p->track); ret=vcd_seek_to_track(vcd,1);
if(ret<0){ if(ret<0){
mp_msg(MSGT_OPEN, MSGL_ERR, "%s (seek)\n", mp_msg(MSGT_OPEN, MSGL_ERR, "%s (seek)\n",
mp_gtext("Error selecting VCD track.")); mp_gtext("Error selecting VCD track."));
close(f); close(f);
free(vcd); free(vcd);
m_struct_free(&stream_opts,opts);
return STREAM_ERROR; return STREAM_ERROR;
} }
/* search forward up to at most 3 seconds to skip leading margin */ /* search forward up to at most 3 seconds to skip leading margin */
@@ -199,7 +174,6 @@ static int open_s(stream_t *stream,int mode, void* opts)
stream->close = close_s; stream->close = close_s;
stream->demuxer = "lavf"; // mpegps ( or "vcd"?) stream->demuxer = "lavf"; // mpegps ( or "vcd"?)
m_struct_free(&stream_opts,opts);
return STREAM_OK; return STREAM_OK;
} }
@@ -207,6 +181,4 @@ const stream_info_t stream_info_vcd = {
"vcd", "vcd",
open_s, open_s,
{ "vcd", NULL }, { "vcd", NULL },
&stream_opts,
1 // Urls are an option string
}; };