"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/xitk/mediamark.c" between
xine-ui-0.99.13.tar.bz2 and xine-ui-0.99.14.tar.bz2

About: xine is a free video player which plays mpeg-2 and mpeg-1 video, DVDs (unlocked/unencrypted only), video CDs, SVCDs, and AVI files (using Win32 codecs) with synchronized audio and video, and optionally fullscreen using the Xv extensions in Xfree86 4.x (user interface).

mediamark.c  (xine-ui-0.99.13.tar.bz2):mediamark.c  (xine-ui-0.99.14.tar.bz2)
/* /*
* Copyright (C) 2000-2021 the xine project * Copyright (C) 2000-2023 the xine project
* *
* This file is part of xine, a unix video player. * This file is part of xine, a unix video player.
* *
* xine is free software; you can redistribute it and/or modify * xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* xine is distributed in the hope that it will be useful, * xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
skipping to change at line 38 skipping to change at line 38
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <ctype.h> #include <ctype.h>
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <xine/sorted_array.h>
#include "common.h" #include "common.h"
#include "mediamark.h" #include "mediamark.h"
#include "download.h" #include "download.h"
#include "file_browser.h" #include "file_browser.h"
#include "panel.h" #include "panel.h"
#include "playlist.h" #include "playlist.h"
#include "videowin.h" #include "videowin.h"
#include "actions.h" #include "actions.h"
#include "event.h" #include "event.h"
#include "errors.h" #include "errors.h"
#include "xine-toolkit/backend.h" #include "xine-toolkit/backend.h"
#include "xine-toolkit/inputtext.h" #include "xine-toolkit/inputtext.h"
#include "xine-toolkit/labelbutton.h" #include "xine-toolkit/labelbutton.h"
#include "xine-toolkit/label.h" #include "xine-toolkit/label.h"
#include "xine-toolkit/intbox.h" #include "xine-toolkit/intbox.h"
#define WINDOW_WIDTH 525 #define WINDOW_WIDTH 525
#define WINDOW_HEIGHT 270 #define WINDOW_HEIGHT 270
struct xui_mmkedit_s { struct xui_mmkedit_s {
gGui_t *gui; gGui_t *gui;
apply_callback_t callback;
void *user_data;
apply_callback_t callback; xitk_window_t *xwin;
void *user_data;
xitk_window_t *xwin; xitk_widget_list_t *widget_list;
xitk_widget_list_t *widget_list; xitk_widget_t *mrl, *ident, *sub;
xitk_widget_t *start, *end, *av_offset, *spu_offset;
xitk_widget_t *ok, *apply, *close;
xitk_widget_t *mrl; uint8_t helipad[4];
xitk_widget_t *ident; int vals[4];
xitk_widget_t *sub;
xitk_widget_t *start;
xitk_widget_t *end;
xitk_widget_t *av_offset;
xitk_widget_t *spu_offset;
mediamark_t **mmk; mediamark_t **mmk;
int visible; int visible;
xitk_register_key_t widget_key; xitk_register_key_t widget_key;
}; };
typedef struct { /** mrl_buf handling ***********************************************************
char *buf1, *buf2, ext[8], **lines; ********/
const char *filename, *type;
size_t size, num_lines, num_words, num_entries;
} _lf_t;
static _lf_t *_lf_new (size_t size) { static const uint8_t tab_unhex[256] = {
_lf_t *lf; 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
uint32_t *w; 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
size_t num_words = (size + 4) & ~4; 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
char *m = malloc (sizeof (*lf) + 2 * num_words); 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16,16,16,16,16,
16,10,11,12,13,14,15,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,10,11,12,13,14,15,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
};
if (!m) { static size_t _gui_string_unescape (char *_s, size_t len) {
fprintf(stderr, "%s(): malloc() failed.\n", __XINE_FUNCTION__); uint8_t *s = (uint8_t *)_s, *e = s + len, *d, save[2];
return NULL;
}
lf = (_lf_t *)m; memcpy (save, e, 2);
lf->ext[0] = 0; memset (e, '%', 2);
lf->filename = ""; s += xitk_find_byte ((char *)s, '%');
lf->type = ""; d = s;
lf->num_entries = 0; while (s < e) {
lf->lines = NULL; uint8_t a = tab_unhex[s[1]], b = tab_unhex[s[2]];
lf->size = size;
lf->num_words = num_words >> 2; if (!((a | b) & 16)) {
m += sizeof (*lf); s += 3;
lf->buf1 = m; *d++ = (a << 4) + b;
w = (uint32_t *)m; } else {
w[lf->num_words - 1] = 0; s += (s[1] == '%') ? 2 : 1;
m += num_words; *d++ = '%';
lf->buf2 = m; }
w = (uint32_t *)m; while (*s != '%')
w[lf->num_words - 1] = 0; *d++ = *s++;
return lf; }
memcpy (e, save, 2);
return d - (uint8_t *)_s;
} }
static char *_lf_dup (_lf_t *lf) { void mrl_buf_init (mrl_buf_t *mrlb) {
free (lf->lines); mrlb->start = mrlb->protend = mrlb->host = mrlb->root = mrlb->lastpart =
lf->lines = NULL; mrlb->ext = mrlb->args = mrlb->info = mrlb->end = mrlb->buf + 8;
memcpy (lf->buf2, lf->buf1, lf->size + 1); mrlb->max = mrlb->buf + sizeof (mrlb->buf) - 8;
return lf->buf2; memset (mrlb->buf, 0, 16);
} }
static int _lf_split_lines (_lf_t *lf) { static void _mrl_buf_working_dir (mrl_buf_t *mrlb) {
if (lf->lines) if (getcwd (mrlb->start, mrlb->max - mrlb->start)) {
return lf->num_lines; mrlb->args = mrlb->start + xitk_find_byte (mrlb->start, 0);
mrlb->start[-1] = '/';
{ if (mrlb->args[-1] != '/') {
uint32_t *w = (uint32_t *)lf->buf2; memcpy (mrlb->args, "/", 2);
size_t n1 = lf->num_words; mrlb->args++;
memcpy (lf->buf2, lf->buf1, lf->num_words << 2);
lf->num_lines = 0;
while (n1) {
uint32_t v = 0;
size_t n2 = n1 > 255 ? 255 : n1;
n1 -= n2;
lf->num_lines += 4 * n2;
while (n2) {
uint32_t t = *w++;
t ^= 0x0a0a0a0a;
t |= t >> 4;
t |= t >> 2;
t |= t >> 1;
t &= 0x01010101;
v += t;
n2 -= 1;
}
lf->num_lines -= (v & 255) + ((v >> 8) & 255) + ((v >> 16) & 255) + (v >>
24);
} }
mrlb->protend = mrlb->host = mrlb->root = mrlb->start;
mrlb->lastpart = mrlb->ext = mrlb->info = mrlb->end = mrlb->args;
} else {
mrl_buf_init (mrlb);
} }
if (lf->size && (lf->buf2[lf->size - 1] != '\n')) }
lf->num_lines += 1;
lf->lines = malloc ((lf->num_lines + 1) * sizeof (*lf->lines));
if (lf->lines) {
char **lb = lf->lines, *p1 = lf->buf2;
while (1) {
char *p2 = strchr (p1, '\n');
if (!p2) static int _mrl_buf_mkdir_p (mrl_buf_t *path) {
struct stat sbuf;
char *p, save;
save = path->lastpart[0];
path->lastpart[0] = '/';
p = path->root;
if (p[0] == '/')
p++;
while (p < path->lastpart) {
p += xitk_find_byte (p, '/');
p[0] = 0;
if (!stat (path->root, &sbuf)) {
if (!S_ISDIR (sbuf.st_mode)) {
p[0] = '/';
break; break;
*lb++ = p1; }
p2[0] = 0; } else if (mkdir (path->root, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
if ((p2 > p1) && (p2[-1] == '\r')) p[0] = '/';
p2[-1] = 0; break;
p1 = p2 + 1;
}
{
char *p2 = lf->buf2 + lf->size;
if ((p2 > p1) && (p2[-1] == '\r'))
*--p2 = 0;
if (p1 < p2)
*lb++ = p1;
} }
*lb = NULL; p[0] = '/';
return lf->num_lines; p++;
} }
return 0; path->lastpart[0] = save;
return p >= path->lastpart;
} }
static void _lf_delete (_lf_t *lf) { static size_t _mrl_buf_resolve_dots (char *s, size_t len) {
lf->buf1 = NULL; uint8_t *start = (uint8_t *)s, *p, *t, *e = start + len, save1[2], save2[2];
lf->buf2 = NULL; /* set safe plugs */
lf->type = NULL; memcpy (save1, start - 2, 2);
free (lf->lines); memcpy (save2, e, 2);
lf->lines = NULL; memcpy (start - 2, "//", 2);
free (lf); memcpy (e, "//", 2);
/* check only part 1 */
for (t = p = start; p < e;) {
uint8_t *here = p;
for (p++; p[0] != '/'; p++) ;
if (here[1] == '.') {
if (here[2] == '/')
break;
if (!memcmp (here + 2, "./", 2)) {
for (t = here - 1; t[0] != '/'; t--) ;
if (t < start)
t = start;
break;
}
}
t = p;
}
/* move part 2 */
if (t < p) {
uint8_t *f;
for (f = p; p < e;) {
uint8_t *here = p;
for (p++; p[0] != '/'; p++) ;
if (here[1] == '.') {
if (here[2] == '/') {
if (here > f) {
memmove (t, f, here - f);
t += here - f;
f = p;
}
} else if (!memcmp (here + 2, "./", 2)) {
if (here > f) {
memmove (t, f, here - f);
t += here - f;
f = p;
}
for (t--; t[0] != '/'; t--) ;
if (t < start)
t = start;
}
}
}
if (p > f) {
memmove (t, f, p - f);
t += p - f;
}
}
/* remove plugs */
memcpy (start - 2, save1, 2);
memcpy (e, save2, 2);
return t - start;
} }
typedef mediamark_t **(*playlist_guess_func_t) (_lf_t *lf); int mrl_buf_set (mrl_buf_t *mrlb, mrl_buf_t *base, const char *name) {
typedef mediamark_t **(*playlist_xml_guess_func_t) (_lf_t *lf, xml_node_t *); size_t size;
char prot[16], save;
char *scan_args;
uint8_t *p;
uint32_t plen;
static _lf_t *_download_file (gGui_t *gui, const char *filename) { if (!name)
_lf_t *lf; return 0;
download_t download; if (!name[0])
return 0;
if ((!filename) || (!filename[0])) { mrlb->start = mrlb->buf + 8;
fprintf (stderr, "%s(): Empty or NULL filename.\n", __XINE_FUNCTION__); size = xitk_find_byte (name, 0);
return NULL; if ((int)size > mrlb->max - mrlb->start)
size = mrlb->max - mrlb->start;
memcpy (mrlb->start, name, size + 1);
mrlb->end = mrlb->start + size;
plen = mrl_get_lowercase_prot (prot, sizeof (prot), mrlb->start);
do {
/* protocol */
mrlb->protend = mrlb->start + plen;
if ((plen == 4) && !memcmp (prot, "file", 4)) {
p = (uint8_t *)mrlb->protend + 2;
if (!memcmp (p, "//", 2))
p++;
mrlb->start = mrlb->protend = mrlb->host = mrlb->root = (char *)p;
break;
}
if (!plen && memcmp (mrlb->protend, ":/", 2)) {
/* plain file or relative path */
mrlb->host = mrlb->root = mrlb->protend;
break;
}
/* host */
p = (uint8_t *)mrlb->protend + 2;
for (; p[0] == '/'; p++) ;
mrlb->host = (char *)p;
/* root */
mrlb->end[0] = '/';
for (; p[0] != '/'; p++) ;
mrlb->end[0] = 0;
mrlb->root = (char *)p;
} while (0);
/* most filesystems accept #, ext even does ?.
* test them after last / only then. */
if (!plen && !(base && !mrl_buf_is_file (base))) {
mrlb->start[-1] = '/';
for (p = (uint8_t *)mrlb->end; p[-1] != '/'; p--) ;
scan_args = (char *)p;
} else {
scan_args = mrlb->root;
} }
/* extra info */
mrlb->end[0] = '#';
mrlb->info = scan_args + xitk_find_byte (scan_args, '#');
mrlb->end[0] = 0;
/* args */
save = mrlb->info[0];
mrlb->info[0] = '?';
mrlb->args = scan_args + xitk_find_byte (scan_args, '?');
mrlb->info[0] = save;
/* file:// */
if ((plen == 4) && !memcmp (prot, "file", 4)) {
mrlb->args = mrlb->start + _gui_string_unescape (mrlb->start, mrlb->args - m
rlb->start);
if (mrlb->info > mrlb->args) {
memmove (mrlb->args, mrlb->info, mrlb->end - mrlb->info + 1);
mrlb->end -= mrlb->info - mrlb->args;
mrlb->info = mrlb->args;
mrlb->end[0] = 0;
}
}
/* last part */
mrlb->start[-1] = '/';
for (p = (uint8_t *)mrlb->args; p[-1] != '/'; p--) ;
mrlb->lastpart = (char *)p;
mrlb->start[-1] = 0;
/* ext */
mrlb->lastpart[-1] = '.';
for (p = (uint8_t *)mrlb->args; p[-1] != '.'; p--) ;
mrlb->lastpart[-1] = '/';
mrlb->ext = p[-1] == '.' ? (char *)p : mrlb->args;
mrlb->start[-1] = 0;
download.gui = gui; return 1;
download.buf = NULL; }
download.error = NULL;
download.size = 0;
download.status = 0;
if (!network_download (filename, &download)) { void mrl_buf_merge (mrl_buf_t *to, mrl_buf_t *base, mrl_buf_t *name) {
gui_msg (gui, XUI_MSG_ERROR, "Unable to download '%s': %s", filename, downlo to->max = to->buf + sizeof (to->buf) - 8;
ad.error); if (name->protend > name->start) {
lf = NULL; /* full new mrl */
memcpy (to->start, name->start, name->end - name->start + 1);
to->protend = to->start + (name->protend - name->start);
to->host = to->start + (name->host - name->start);
to->root = to->start + (name->root - name->start);
to->lastpart = to->start + (name->lastpart - name->start);
to->ext = to->start + (name->ext - name->start);
to->args = to->start + (name->args - name->start);
to->info = to->start + (name->info - name->start);
to->end = to->start + (name->end - name->start);
} else if (name->host > name->protend) {
/* yes i havr seen "://host/foo/bar" :-) */
if (to != base) {
int l = base->protend - base->start;
if (l > 0)
memcpy (to->start, base->start, l);
to->protend = to->start + (base->protend - base->start);
}
memcpy (to->protend, name->start, name->end - name->start + 1);
to->host = to->protend + (name->host - name->start);
to->root = to->protend + (name->root - name->start);
to->lastpart = to->protend + (name->lastpart - name->start);
to->ext = to->protend + (name->ext - name->start);
to->args = to->protend + (name->args - name->start);
to->info = to->protend + (name->info - name->start);
to->end = to->protend + (name->end - name->start);
} else if (name->root[0] == '/') {
/* absolute path on same host */
if (to != base) {
int l = base->root - base->start;
if (l > 0)
memcpy (to->start, base->start, l);
to->protend = to->start + (base->protend - base->start);
to->host = to->start + (base->host - base->start);
to->root = to->start + (base->root - base->start);
}
memcpy (to->root, name->start, name->end - name->start + 1);
to->lastpart = to->root + (name->lastpart - name->start);
to->ext = to->root + (name->ext - name->start);
to->args = to->root + (name->args - name->start);
to->info = to->root + (name->info - name->start);
to->end = to->root + (name->end - name->start);
} else { } else {
lf = _lf_new (download.size); /* relative path */
if (lf) int l;
memcpy (lf->buf1, download.buf, lf->size); if (to != base) {
l = base->lastpart - base->start;
if (l > 0)
memcpy (to->start, base->start, l);
to->protend = to->start + (base->protend - base->start);
to->host = to->start + (base->host - base->start);
to->root = to->start + (base->root - base->start);
to->lastpart = to->start + (base->lastpart - base->start);
}
memcpy (to->lastpart , name->start, name->end - name->start + 1);
to->ext = to->lastpart + (name->ext - name->start);
to->args = to->lastpart + (name->args - name->start);
to->info = to->lastpart + (name->info - name->start);
to->end = to->lastpart + (name->end - name->start);
to->lastpart += name->lastpart - name->start;
l = to->lastpart - to->root;
l -= _mrl_buf_resolve_dots (to->root, l);
if (l > 0) {
memmove (to->lastpart - l, to->lastpart, to->end - to->lastpart + 1);
to->lastpart -= l;
to->ext -= l;
to->args -= l;
to->info -= l;
to->end -= l;
}
}
/* security */
if (!mrl_buf_is_file (base)) {
to->info[0] = 0;
} }
SAFE_FREE (download.buf);
SAFE_FREE (download.error);
return lf;
} }
#if 0 int mrl_buf_is_file (mrl_buf_t *mrlb) {
static int _file_exist(char *filename) { return mrlb->root == mrlb->start;
struct stat st; }
if(filename && (stat(filename, &st) == 0)) /** basic mediamark_t **********************************************************
return 1; ********/
static int _mediamark_new_from_mrl_buf (mediamark_t **m, const char *ident, mrl_
buf_t *mrl, mrl_buf_t *sub) {
mediamark_t *n;
size_t l;
return 0; if (*m)
} return 0;
#endif *m = n = calloc (1, sizeof (*n));
if (!n)
return 0;
int mrl_look_like_playlist (const char *mrl) { l = mrl->end - mrl->start;
/* TJ. I dont know whether someone really needs to treat n->mrl = malloc (l + 1);
* "foo/bar.m3under/the/table" as an m3u playlist. if (n->mrl) {
* Lets keep this behaviour for now, but make sure that memcpy (n->mrl, mrl->start, l + 1);
* hls (.m3u8) goes to xine-lib verbatim. */ n->mrl[l] = 0;
const char *extension = strrchr (mrl, '.');
if (extension) {
/* All known playlist ending */
if ((!strncasecmp (extension, ".asx", 4)) ||
(!strncasecmp (extension, ".smi", 4)) ||
/*(!strncasecmp (extension, ".smil", 5)) || caught by ".smi" */
(!strncasecmp (extension, ".pls", 4)) ||
(!strncasecmp (extension, ".sfv", 4)) ||
(!strncasecmp (extension, ".xml", 4)) ||
(!strncasecmp (extension, ".tox", 4)) ||
(!strncasecmp (extension, ".fxd", 4)))
return 1;
if ((!strncasecmp (extension, ".m3u", 4)) && (extension[4] != '8'))
return 1;
} }
return 0;
}
static _lf_t *_read_file (gGui_t *gui, const char *filename) { n->ident = n->mrl;
struct stat st; l = ident ? xitk_find_byte (ident, 0) : 0;
_lf_t *lf; if (!l) {
int fd, bytes_read; ident = mrl->lastpart;
size_t size; l = mrl->args - mrl->lastpart;
if ((!filename) || (!filename[0])) {
fprintf (stderr, "%s(): Empty or NULL filename.\n", __XINE_FUNCTION__);
return NULL;
} }
if (l) {
if (mrl_look_like_playlist (filename) && is_downloadable ((char *)filename)) n->ident = malloc (l + 1);
return _download_file (gui, filename); if (n->ident) {
memcpy (n->ident, ident, l);
if (stat (filename, &st) < 0) { n->ident[l] = 0;
fprintf (stderr, "%s(): Unable to stat() '%s' file: %s.\n", __XINE_FUNCTION_ }
_, filename, strerror (errno));
return NULL;
} }
if ((size = st.st_size) == 0) { if (sub) {
fprintf(stderr, "%s(): File '%s' is empty.\n", __XINE_FUNCTION__, filename); l = sub->end - sub->start;
return NULL; if (l) {
n->sub = malloc (l + 1);
if (n->sub) {
memcpy (n->sub, sub->start, l);
n->sub[l] = 0;
}
}
} }
if ((fd = xine_open_cloexec (filename, O_RDONLY)) == -1) { n->end = -1;
fprintf (stderr, "%s(): open(%s) failed: %s.\n", __XINE_FUNCTION__, filename return 1;
, strerror (errno)); }
return NULL;
}
lf = _lf_new (size); int mediamark_copy (mediamark_t **to, const mediamark_t *from) {
if (!lf) { const char *_ident, *_mrl, *_sub, *_none = "";
close (fd); mediamark_t *m;
return NULL; int n = 1;
if (!to || !from)
return 0;
if (!*to) {
*to = calloc (1, sizeof (**to));
if (!*to)
return 0;
} }
m = *to;
if ((bytes_read = read (fd, lf->buf1, size)) != (int)size) { _mrl = from->mrl ? from->mrl : _none;
fprintf (stderr, "%s(): read() return wrong size (%d / %d): %s.\n", _ident = from->ident ? from->ident : _mrl;
__XINE_FUNCTION__, bytes_read, (int)size, strerror (errno)); _sub = from->sub;
lf->size = bytes_read;
if ((_ident != _mrl) && !strcmp (_ident, _mrl))
_ident = _mrl;
if (_ident == _mrl) {
if (!m->ident || strcmp (m->ident, _ident) || !m->mrl || strcmp (m->mrl, _mr
l)) {
char *s = strdup (_ident);
if (s) {
if (m->ident != m->mrl)
free (m->ident);
free (m->mrl);
m->ident = m->mrl = s;
n += 2;
}
}
} else {
if (!m->ident || strcmp (m->ident, _ident)) {
char *s = strdup (_ident);
if (s) {
if (m->ident != m->mrl)
free (m->ident);
m->ident = s;
n++;
}
}
if (!m->mrl || strcmp (m->mrl, _mrl)) {
char *s = strdup (_mrl);
if (s) {
if (m->ident != m->mrl)
free (m->mrl);
m->mrl = s;
n++;
}
}
} }
if ((_sub && !m->sub)
|| (!_sub && m->sub)
|| (_sub && m->sub && strcmp (_sub, m->sub))) {
free (m->sub);
m->sub = _sub ? strdup (_sub) : NULL;
n++;
}
if (m->start != from->start)
m->start = from->start, n++;
if (m->end != from->end)
m->end = from->end, n++;
if (m->av_offset != from->av_offset)
m->av_offset = from->av_offset, n++;
if (m->spu_offset != from->spu_offset)
m->spu_offset = from->spu_offset, n++;
m->type = from->type;
m->from = from->from;
if (m->got_alternate == from->got_alternate)
m->got_alternate = from->got_alternate, n++;
mediamark_duplicate_alternates (from, m);
return n;
}
close (fd); int mediamark_set_str_val (mediamark_t **mmk, const char *value, mmk_val_t what)
{
if (!mmk)
return 0;
if (!*mmk)
return 0;
return lf; switch (what) {
} case MMK_VAL_MRL:
if (!value)
value = "";
if ((*mmk)->mrl && !strcmp ((*mmk)->mrl, value))
return 0;
if ((*mmk)->ident != (*mmk)->mrl) {
if ((*mmk)->ident && !strcmp ((*mmk)->ident, value)) {
free ((*mmk)->mrl);
(*mmk)->mrl = (*mmk)->ident;
return 1;
}
free ((*mmk)->mrl);
}
(*mmk)->mrl = strdup (value);
break;
case MMK_VAL_IDENT:
if (!value || !value[0]) {
if ((*mmk)->ident == (*mmk)->mrl)
return 0;
free ((*mmk)->ident);
(*mmk)->ident = (*mmk)->mrl;
return 1;
}
if ((*mmk)->ident && !strcmp ((*mmk)->ident, value))
return 0;
if ((*mmk)->ident != (*mmk)->mrl) {
if ((*mmk)->mrl && !strcmp ((*mmk)->mrl, value)) {
free ((*mmk)->ident);
(*mmk)->ident = (*mmk)->mrl;
return 1;
}
free ((*mmk)->ident);
}
(*mmk)->ident = strdup (value);
break;
static void _lf_ext (_lf_t *lf, const char *filename) { case MMK_VAL_SUB:
const char *p = filename, *eb = NULL; free ((*mmk)->sub);
(*mmk)->sub = value ? strdup (value) : NULL;
break;
lf->filename = filename; case MMK_VAL_ADD_ALTER:
while (p[0]) { mediamark_append_alternate_mrl (*mmk, value);
if ((p[0] == '?') || (p[0] == '#')) (*mmk)->got_alternate = 1;
break; break;
if (p[0] == '/')
eb = NULL;
else if (p[0] == '.')
eb = p + 1;
p += 1;
}
if (eb) {
size_t el = p - eb;
if (el > sizeof (lf->ext) - 1) default:
el = sizeof (lf->ext) - 1; return 0;
memcpy (lf->ext, eb, el);
lf->ext[el] = 0;
} }
return 1;
} }
int mediamark_have_alternates(mediamark_t *mmk) { int mediamark_free (mediamark_t **mmk) {
if(mmk && mmk->alternates) if (mmk && *mmk) {
mediamark_free_alternates (*mmk);
if ((*mmk)->ident != (*mmk)->mrl)
free ((*mmk)->ident);
(*mmk)->ident = NULL;
SAFE_FREE ((*mmk)->mrl);
SAFE_FREE ((*mmk)->sub);
SAFE_FREE (*mmk);
return 1; return 1;
}
return 0; return 0;
} }
void mediamark_free_alternates(mediamark_t *mmk) { void mediamark_free_alternates(mediamark_t *mmk) {
if(mmk && mediamark_have_alternates(mmk)) { if(mmk && mediamark_have_alternates(mmk)) {
alternate_t *alt = mmk->alternates; alternate_t *alt = mmk->alternates;
while(alt) { while(alt) {
alternate_t *c_alt = alt; alternate_t *c_alt = alt;
free(alt->mrl); free(alt->mrl);
c_alt = alt; c_alt = alt;
alt = alt->next; alt = alt->next;
free(c_alt); free(c_alt);
} }
mmk->alternates = NULL; mmk->alternates = NULL;
mmk->cur_alt = NULL; mmk->cur_alt = NULL;
} }
} }
char *mediamark_get_first_alternate_mrl(mediamark_t *mmk) {
if(mmk && mmk->alternates) { char *mediamark_get_first_alternate_mrl (mediamark_t *mmk) {
if (mmk && mmk->alternates) {
mmk->cur_alt = mmk->alternates; mmk->cur_alt = mmk->alternates;
return mmk->cur_alt->mrl; return mmk->cur_alt->mrl;
} }
return NULL; return NULL;
} }
char *mediamark_get_next_alternate_mrl(mediamark_t *mmk) {
if(mmk && mmk->cur_alt) { char *mediamark_get_next_alternate_mrl (mediamark_t *mmk) {
if(mmk->cur_alt->next) { if (mmk && mmk->cur_alt) {
if (mmk->cur_alt->next) {
mmk->cur_alt = mmk->cur_alt->next; mmk->cur_alt = mmk->cur_alt->next;
return mmk->cur_alt->mrl; return mmk->cur_alt->mrl;
} }
} }
return NULL; return NULL;
} }
char *mediamark_get_current_alternate_mrl(mediamark_t *mmk) {
char *mediamark_get_current_alternate_mrl (mediamark_t *mmk) {
if(mmk && mmk->cur_alt) if(mmk && mmk->cur_alt)
return mmk->cur_alt->mrl; return mmk->cur_alt->mrl;
return NULL; return NULL;
} }
void mediamark_append_alternate_mrl(mediamark_t *mmk, const char *mrl) {
void mediamark_append_alternate_mrl (mediamark_t *mmk, const char *mrl) {
if(mmk && mrl) { if(mmk && mrl) {
alternate_t *alt; alternate_t *alt;
alt = (alternate_t *) calloc(1, sizeof(alternate_t)); alt = (alternate_t *) calloc(1, sizeof(alternate_t));
alt->mrl = strdup(mrl); alt->mrl = strdup(mrl);
alt->next = NULL; alt->next = NULL;
if(mmk->alternates) { if (mmk->alternates) {
alternate_t *p_alt = mmk->alternates; alternate_t *p_alt = mmk->alternates;
while(p_alt->next) while (p_alt->next)
p_alt = p_alt->next; p_alt = p_alt->next;
p_alt->next = alt; p_alt->next = alt;
} }
else else
mmk->alternates = alt; mmk->alternates = alt;
} }
} }
void mediamark_duplicate_alternates(mediamark_t *s_mmk, mediamark_t *d_mmk) {
if(s_mmk && s_mmk->alternates && d_mmk) { void mediamark_duplicate_alternates (const mediamark_t *s_mmk, mediamark_t *d_mm
k) {
if (s_mmk && s_mmk->alternates && d_mmk) {
alternate_t *alt; alternate_t *alt;
if((alt = s_mmk->alternates)) { if((alt = s_mmk->alternates)) {
alternate_t *c_alt, *p_alt = NULL, *t_alt = NULL; alternate_t *c_alt, *p_alt = NULL, *t_alt = NULL;
while(alt) { while(alt) {
c_alt = (alternate_t *) calloc(1, sizeof(alternate_t)); c_alt = (alternate_t *) calloc(1, sizeof(alternate_t));
c_alt->mrl = strdup(alt->mrl); c_alt->mrl = strdup(alt->mrl);
c_alt->next = NULL; c_alt->next = NULL;
skipping to change at line 424 skipping to change at line 700
alt = alt->next; alt = alt->next;
} }
d_mmk->alternates = t_alt; d_mmk->alternates = t_alt;
d_mmk->cur_alt = NULL; d_mmk->cur_alt = NULL;
} }
} }
} }
int mediamark_got_alternate(mediamark_t *mmk) {
if(mmk && mmk->got_alternate) int mediamark_got_alternate (mediamark_t *mmk) {
if (mmk && mmk->got_alternate)
return 1; return 1;
return 0; return 0;
} }
void mediamark_set_got_alternate(mediamark_t *mmk) {
if(mmk) void mediamark_unset_got_alternate (mediamark_t *mmk) {
mmk->got_alternate = 1;
}
void mediamark_unset_got_alternate(mediamark_t *mmk) {
if(mmk) if(mmk)
mmk->got_alternate = 0; mmk->got_alternate = 0;
} }
int mediamark_store_mmk(mediamark_t **mmk,
const char *mrl, const char *ident, const char *sub,
int start, int end, int av_offset, int spu_offset) {
if(mmk && mrl) { /** gui currently played item ************************************************** ********/
(*mmk) = (mediamark_t *) calloc(1, sizeof(mediamark_t)); int gui_current_set_index (gGui_t *gui, int idx) {
(*mmk)->mrl = strdup(mrl); mediamark_t *mmk, *d, none;
(*mmk)->ident = strdup((ident != NULL) ? ident : mrl);
(*mmk)->sub = (sub != NULL) ? strdup(sub) : NULL;
(*mmk)->start = start;
(*mmk)->end = end;
(*mmk)->av_offset = av_offset;
(*mmk)->spu_offset = spu_offset;
(*mmk)->played = 0;
(*mmk)->got_alternate = 0;
(*mmk)->cur_alt = NULL;
(*mmk)->alternates = NULL;
return 1; if (!gui)
return GUI_MMK_NONE;
gui_playlist_lock (gui);
if (idx == GUI_MMK_CURRENT)
idx = gui->playlist.cur;
if ((idx >= 0) && (idx < gui->playlist.num) && gui->playlist.mmk && gui->playl
ist.mmk[idx]) {
mmk = gui->playlist.mmk[idx];
} else {
memset (&none, 0, sizeof (none));
none.end = -1;
/* TRANSLATORS: only ASCII characters (skin) */
none.mrl = (char *)pgettext ("skin", "There is no MRL."); /** will not be wr
itten to. */
none.ident = (char *)("xine-ui version " VERSION);
mmk = &none;
idx = GUI_MMK_NONE;
}
gui->playlist.cur = idx;
d = &gui->mmk;
mediamark_copy (&d, mmk);
gui_playlist_unlock (gui);
gui_pl_updated (gui);
return idx;
}
void gui_current_free (gGui_t *gui) {
gui_playlist_lock (gui);
if (gui->mmk.ident != gui->mmk.mrl)
free (gui->mmk.ident);
gui->mmk.ident = NULL;
SAFE_FREE (gui->mmk.mrl);
SAFE_FREE (gui->mmk.sub);
if (mediamark_have_alternates (&(gui->mmk)))
mediamark_free_alternates (&(gui->mmk));
gui_playlist_unlock (gui);
}
/** gui playlist ***************************************************************
********/
typedef union {
char z[4];
uint32_t v;
} known_ext_t;
static const known_ext_t _audio_exts[] = {
{"aac "}, {"ac3 "}, {"aif "}, {"aiff"}, {"au "}, {"aud "}, {"mp2 "}, {"mp3 "}
,
{"mp4a"}, {"mpa "}, {"nsf "}, {"ogg "}, {"ogm "}, {"opus"}, {"pva "}, {"ra "}
,
{"snd "}, {"spx "}, {"wav "}, {"voc "}, {"vox "}, {"wma "}, {"vqa "}, {"xa "}
,
{"xa1 "}, {"xa2 "}, {"xap "}, {"xas "}
};
static const known_ext_t _video_exts[] = {
{"4xm "}, {"asf "}, {"avi "}, {"cak "}, {"cin "}, {"cpk "}, {"dat "}, {"dif "}
,
{"dps "}, {"dv "}, {"film"}, {"flc "}, {"fli "}, {"flv "}, {"ik2 "}, {"iki "}
,
{"m2p "}, {"m2t "}, {"mjpg"}, {"mkv "}, {"mng "}, {"mov "}, {"mp4 "}, {"mp4v"}
,
{"mpeg"}, {"mpg "}, {"mpv "}, {"mv8 "}, {"mve "}, {"nsv "}, {"pes "}, {"qt "}
,
{"ram "}, {"rm "}, {"rmvb"}, {"roq "}, {"str "}, {"trp "}, {"ts "}, {"vob "}
,
{"wax "}, {"webm"}, {"wmv "}, {"wve "}, {"wvx "}, {"y4m "}
};
static const known_ext_t _image_exts[] = {
{"bmp "}, {"gif "}, {"iff "}, {"jpeg"}, {"jpg "}, {"png "}, {"tif "}, {"tiff"}
,
{"webp"}
};
static const known_ext_t _spu_exts[] = {
{"asc "}, {"ass "}, {"smi "}, {"srt "}, {"ssa "}, {"sub "}, {"txt "}
};
static const known_ext_t _playlist_exts[] = {
{"asx "}, {"fxd "}, {"m3u "}, {"pls "}, {"sfv "}, {"smi "}, {"smil"}, {"tox "}
,
{"xml "}
};
static int _known_ext_cmp (void *a, void *b) {
uint32_t d = (uintptr_t)a, e = (uintptr_t)b;
return (int)d - (int)e;
}
#if defined(XINE_SARRAY) && (XINE_SARRAY >= 3)
static unsigned int _known_ext_hash (void *a) {
uint32_t v = (uintptr_t)a;
v ^= v >> 16;
v ^= v >> 8;
return v & 31;
}
#endif
static xine_sarray_t *_set_known_exts (const known_ext_t *exts, uint32_t n) {
xine_sarray_t *a = xine_sarray_new (n, _known_ext_cmp);
uint32_t u;
#if defined(XINE_SARRAY) && (XINE_SARRAY >= 3)
xine_sarray_set_hash (a, _known_ext_hash, 32);
#endif
for (u = 0; u < n; u++)
xine_sarray_add (a, (void *)(uintptr_t)exts[u].v);
return a;
}
static int _is_known_ext (xine_sarray_t *a, uint32_t ext) {
return (ext == 0x20202020) ? 0 : xine_sarray_binary_search (a, (void *)(uintpt
r_t)ext) >= 0;
}
static uint32_t _get_ext_val (const char *s, uint32_t l) {
known_ext_t ext;
uint32_t u;
/* allow 5 so "mpeg" gets "mpega" and "mpegv" as well. */
if (!l || (l > 5))
return 0x20202020;
if (l == 5)
l = 4;
ext.v = 0x20202020;
for (u = 0; u < l; u++)
ext.z[u] = s[u];
return ext.v | 0x20202020;
}
void gui_playlist_init (gGui_t *gui) {
int i;
void *v;
if (!gui)
return;
gui->playlist.mmk = NULL;
gui->playlist.max = 0;
gui->playlist.num = 0;
gui->playlist.cur = -1;
gui->playlist.ref_append = 0;
gui->playlist.loop = PLAYLIST_LOOP_NO_LOOP;
gui->playlist.control = 0;
gui->playlist.exts[XUI_EXTS_ANY] = NULL;
gui->playlist.exts[XUI_EXTS_AUDIO] = _set_known_exts (_audio_exts, sizeof (_au
dio_exts) / sizeof (_audio_exts[0]));
gui->playlist.exts[XUI_EXTS_VIDEO] = _set_known_exts (_video_exts, sizeof (_vi
deo_exts) / sizeof (_video_exts[0]));
gui->playlist.exts[XUI_EXTS_IMAGE] = _set_known_exts (_image_exts, sizeof (_im
age_exts) / sizeof (_image_exts[0]));
gui->playlist.exts[XUI_EXTS_MEDIA] = xine_sarray_new (
xine_sarray_size (gui->playlist.exts[XUI_EXTS_VIDEO]) +
xine_sarray_size (gui->playlist.exts[XUI_EXTS_AUDIO]) +
xine_sarray_size (gui->playlist.exts[XUI_EXTS_IMAGE]),
_known_ext_cmp);
#if defined(XINE_SARRAY) && (XINE_SARRAY >= 3)
xine_sarray_set_hash (gui->playlist.exts[XUI_EXTS_MEDIA], _known_ext_hash, 32)
;
#endif
for (i = 0; (v = xine_sarray_get (gui->playlist.exts[XUI_EXTS_VIDEO], i)) != N
ULL; i++)
xine_sarray_add (gui->playlist.exts[XUI_EXTS_MEDIA], v);
for (i = 0; (v = xine_sarray_get (gui->playlist.exts[XUI_EXTS_AUDIO], i)) != N
ULL; i++)
xine_sarray_add (gui->playlist.exts[XUI_EXTS_MEDIA], v);
for (i = 0; (v = xine_sarray_get (gui->playlist.exts[XUI_EXTS_IMAGE], i)) != N
ULL; i++)
xine_sarray_add (gui->playlist.exts[XUI_EXTS_MEDIA], v);
gui->playlist.exts[XUI_EXTS_PLAYLIST] = _set_known_exts (_playlist_exts, sizeo
f (_playlist_exts) / sizeof (_playlist_exts[0]));
gui->playlist.exts[XUI_EXTS_SUBTITLE] = _set_known_exts (_spu_exts, sizeof (_s
pu_exts) / sizeof (_spu_exts[0]));
}
void gui_playlist_deinit (gGui_t *gui) {
int i;
if (!gui)
return;
if (gui->playlist.mmk) {
for (i = gui->playlist.num - 1; i >= 0; i--)
mediamark_free (gui->playlist.mmk + i);
SAFE_FREE (gui->playlist.mmk);
} }
gui->playlist.max = 0;
gui->playlist.num = 0;
gui->playlist.cur = -1;
gui->playlist.ref_append = 0;
gui->playlist.loop = 0;
gui->playlist.control = 0;
for (i = XUI_EXTS_ANY; i < XUI_EXTS_LAST; i++) {
xine_sarray_delete (gui->playlist.exts[i]);
gui->playlist.exts[i] = NULL;
}
}
int mrl_look_like_playlist (gGui_t *gui, const char *mrl) {
#if 1
mrl_buf_t mrlb;
if (!gui)
return 0;
mrl_buf_init (&mrlb);
if (!mrl_buf_set (&mrlb, NULL, mrl))
return 0;
if ((mrlb.ext >= mrlb.args) || (mrlb.ext + 5 < mrlb.args))
return 0;
return _is_known_ext (gui->playlist.exts[XUI_EXTS_PLAYLIST], _get_ext_val (mrl
b.ext, mrlb.args - mrlb.ext));
#else
/* TJ. I dont know whether someone really needs to treat
* "foo/bar.m3under/the/table" as an m3u playlist.
* Lets keep this behaviour for now, but make sure that
* hls (.m3u8) goes to xine-lib verbatim. */
const char *extension = strrchr (mrl, '.');
(void)gui;
if (extension) {
/* All known playlist ending */
if ((!strncasecmp (extension, ".asx", 4)) ||
(!strncasecmp (extension, ".smi", 4)) ||
/*(!strncasecmp (extension, ".smil", 5)) || caught by ".smi" */
(!strncasecmp (extension, ".pls", 4)) ||
(!strncasecmp (extension, ".sfv", 4)) ||
(!strncasecmp (extension, ".xml", 4)) ||
(!strncasecmp (extension, ".tox", 4)) ||
(!strncasecmp (extension, ".fxd", 4)))
return 1;
if ((!strncasecmp (extension, ".m3u", 4)) && (extension[4] != '8'))
return 1;
}
return 0; return 0;
#endif
} }
mediamark_t *mediamark_clone_mmk(mediamark_t *mmk) { int gui_playlist_set_str_val (gGui_t *gui, const char *value, mmk_val_t what, in
mediamark_t *cmmk = NULL; t idx) {
gui_playlist_lock (gui);
if (idx == GUI_MMK_CURRENT)
idx = gui->playlist.cur;
if ((idx >= 0) && (idx < gui->playlist.num) && gui->playlist.mmk)
idx = mediamark_set_str_val (&gui->playlist.mmk[idx], value, what);
else
idx = GUI_MMK_NONE;
gui_playlist_unlock (gui);
return idx;
}
if(mmk && mmk->mrl) { mediamark_t *mediamark_get_current_mmk (gGui_t *gui) {
cmmk = (mediamark_t *) calloc(1, sizeof(mediamark_t)); if(gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
cmmk->mrl = strdup(mmk->mrl); gui->playlist.mmk[gui->playlist.cur])
cmmk->ident = (mmk->ident) ? strdup(mmk->ident) : NULL; return gui->playlist.mmk[gui->playlist.cur];
cmmk->sub = (mmk->sub) ? strdup(mmk->sub) : NULL;
cmmk->start = mmk->start; return (mediamark_t *) NULL;
cmmk->end = mmk->end; }
cmmk->av_offset = mmk->av_offset;
cmmk->spu_offset = mmk->spu_offset; mediamark_t *mediamark_get_mmk_by_index (gGui_t *gui, int index) {
cmmk->played = mmk->played; if(index < gui->playlist.num && index >= 0 && gui->playlist.mmk &&
cmmk->got_alternate = mmk->got_alternate; gui->playlist.mmk[index])
mediamark_duplicate_alternates(mmk, cmmk); return gui->playlist.mmk[index];
}
return (mediamark_t *) NULL;
return cmmk; }
}
const char *mediamark_get_current_mrl (gGui_t *gui) {
int mediamark_free_mmk(mediamark_t **mmk) { if(gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
if((*mmk) != NULL) { gui->playlist.mmk[gui->playlist.cur] &&
mediamark_free_alternates((*mmk)); gui->playlist.cur < gui->playlist.num)
SAFE_FREE((*mmk)->ident); return gui->playlist.mmk[gui->playlist.cur]->mrl;
SAFE_FREE((*mmk)->mrl);
SAFE_FREE((*mmk)->sub); return NULL;
SAFE_FREE((*mmk)); }
return 1;
const char *mediamark_get_current_ident (gGui_t *gui) {
if(gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
gui->playlist.mmk[gui->playlist.cur])
return gui->playlist.mmk[gui->playlist.cur]->ident;
return NULL;
}
typedef struct {
char *buf1, *buf2, ext[8], **lines;
mrl_buf_t *base, mrl, sub, item;
const char *type;
size_t size, num_lines, num_entries;
mediamark_t **mmk;
uint32_t have, used;
} _lf_t;
static int _lf_add (_lf_t *lf, int index, const mediamark_t *mmk) {
if (index < 0)
return 0;
if ((uint32_t)index >= lf->have) {
uint32_t nhave = (index + 32) & ~31;
mediamark_t **n = realloc (lf->mmk, nhave * sizeof (*n));
if (!n)
return 0;
memset (n + lf->have, 0, (nhave - lf->have) * sizeof (*n));
lf->mmk = n;
lf->have = nhave;
} }
return 0; if (!mmk)
return 0;
if ((uint32_t)index >= lf->used)
lf->used = index + 1;
if (mrl_buf_set (&lf->item, lf->base, mmk->mrl))
mrl_buf_merge (&lf->mrl, lf->base, &lf->item);
else
mrl_buf_init (&lf->mrl);
if (mrl_buf_set (&lf->item, lf->base, mmk->sub))
mrl_buf_merge (&lf->sub, lf->base, &lf->item);
else
mrl_buf_init (&lf->sub);
if (!_mediamark_new_from_mrl_buf (lf->mmk + index, mmk->ident, &lf->mrl, &lf->
sub))
return 0;
lf->mmk[index]->start = mmk->start;
lf->mmk[index]->end = mmk->end;
lf->mmk[index]->av_offset = mmk->av_offset;
lf->mmk[index]->spu_offset = mmk->spu_offset;
lf->mmk[index]->type = mmk->type;
lf->mmk[index]->from = mmk->from;
return 1;
}
static void _lf_add2 (_lf_t *lf, mediamark_t *mmk) {
if (lf->used >= lf->have) {
mediamark_t **n = realloc (lf->mmk, (lf->have + 32) * sizeof (*n));
if (!n) {
mediamark_t *_mmk = mmk;
mediamark_free (&_mmk);
return;
}
lf->mmk = n;
lf->have += 32;
}
lf->mmk[lf->used++] = mmk;
} }
static char *get_basedir(const char *filename) { static _lf_t *_lf_new (mrl_buf_t *name, size_t size) {
char *path; _lf_t *lf;
char *origin = NULL; size_t need = (size + 4 + 1 + 4 + 3) & ~3;
char *m = malloc (sizeof (*lf) + 2 * need);
path = strrchr(filename, '/'); if (!m) {
if(path && (path > filename)) { fprintf(stderr, "%s(): malloc() failed.\n", __XINE_FUNCTION__);
origin = (char *) malloc((path - filename) + 2); return NULL;
snprintf(origin, (path-filename)+2, "%s", filename);
} }
return origin; lf = (_lf_t *)m;
lf->ext[0] = 0;
lf->base = name;
mrl_buf_init (&lf->mrl);
mrl_buf_init (&lf->sub);
mrl_buf_init (&lf->item);
lf->type = "";
lf->num_entries = 0;
lf->lines = NULL;
lf->size = size;
m += sizeof (*lf);
memset (m, 0, 4);
lf->buf1 = m + 4;
m += need;
memset (m - 4, 0, 8);
lf->buf2 = m + 4;
memset (m + need - 4, 0, 4);
lf->mmk = NULL;
lf->have = 0;
lf->used = 0;
return lf;
}
static char *_lf_dup (_lf_t *lf) {
free (lf->lines);
lf->lines = NULL;
memcpy (lf->buf2, lf->buf1, lf->size + 1);
return lf->buf2;
} }
static int is_mrl(const char *entry) { static int _lf_split_lines (_lf_t *lf) {
char *path; char *line, *nextline;
uint32_t have, used;
path = strstr(entry, ":/"); if (lf->lines)
if (path) { return lf->num_lines;
while (entry < path) {
if (!isalnum(entry[0])) return 0; have = used = 0;
entry++; memcpy (lf->buf2, lf->buf1, lf->size);
lf->buf2[-1] = 0;
lf->buf2[lf->size] = '\n';
for (line = lf->buf2; line < lf->buf2 + lf->size; line = nextline) {
char *lend;
if (used + 3 > have) {
char **n = realloc (lf->lines, (have + 128) * sizeof (*n));
if (!n)
break;
lf->lines = n;
have += 128;
} }
return 1; lend = line + xitk_find_byte (line, '\n');
nextline = lend + 1;
lend[0] = 0;
if (lend[-1] == '\r')
*--lend = 0;
if (lend > line)
lf->lines[used++] = line;
} }
return 0; line[0] = 0;
if (lf->lines) {
lf->lines[used] = line;
lf->lines[used + 1] = NULL;
}
lf->num_lines = used;
return used;
} }
static const char *concat_basedir(char *buffer, size_t size, const char *origin, static void _lf_delete (_lf_t *lf) {
const char *entry) { lf->buf1 = NULL;
if(origin && entry[0] != '/' && !is_mrl(entry)) { lf->buf2 = NULL;
snprintf(buffer, size, "%s%s", origin, entry); lf->type = NULL;
return buffer; free (lf->lines);
lf->lines = NULL;
free (lf->mmk);
lf->mmk = NULL;
free (lf);
}
typedef void (*playlist_guess_func_t) (_lf_t *lf);
typedef void (*playlist_xml_guess_func_t) (_lf_t *lf, xml_node_t *);
static _lf_t *_download_file (gGui_t *gui, mrl_buf_t *name) {
_lf_t *lf;
download_t download;
download.gui = gui;
download.buf = NULL;
download.error = NULL;
download.size = 0;
download.status = 0;
if (!network_download (name->start, &download)) {
gui_msg (gui, XUI_MSG_ERROR, "Unable to download '%s': %s", name->start, dow
nload.error);
lf = NULL;
} else { } else {
return entry; lf = _lf_new (name, download.size);
if (lf)
memcpy (lf->buf1, download.buf, lf->size);
} }
SAFE_FREE (download.buf);
SAFE_FREE (download.error);
return lf;
}
#if 0
static int _file_exist(char *filename) {
struct stat st;
if(filename && (stat(filename, &st) == 0))
return 1;
return 0;
}
#endif
static void _lf_ext (_lf_t *lf) {
size_t el = lf->base->args - lf->base->ext;
if (el > sizeof (lf->ext) - 1)
el = sizeof (lf->ext) - 1;
memcpy (lf->ext, lf->base->ext, el);
lf->ext[el] = 0;
}
static _lf_t *_lf_get (gGui_t *gui, mrl_buf_t *name) {
struct stat st;
_lf_t *lf;
int fd, bytes_read;
size_t size;
if (!mrl_buf_is_file (name))
return _download_file (gui, name);
if (stat (name->start, &st) < 0) {
fprintf (stderr, "%s(): Unable to stat() '%s' file: %s.\n", __XINE_FUNCTION_
_, name->start, strerror (errno));
return NULL;
}
if ((size = st.st_size) == 0) {
fprintf (stderr, "%s(): File '%s' is empty.\n", __XINE_FUNCTION__, name->sta
rt);
return NULL;
}
if ((fd = xine_open_cloexec (name->start, O_RDONLY)) == -1) {
fprintf (stderr, "%s(): open(%s) failed: %s.\n", __XINE_FUNCTION__, name->st
art, strerror (errno));
return NULL;
}
lf = _lf_new (name, size);
if (!lf) {
close (fd);
return NULL;
}
if ((bytes_read = read (fd, lf->buf1, size)) != (int)size) {
fprintf (stderr, "%s(): read() return wrong size (%d / %d): %s.\n",
__XINE_FUNCTION__, bytes_read, (int)size, strerror (errno));
lf->size = bytes_read;
}
close (fd);
_lf_ext (lf);
return lf;
} }
/* /*
* Playlists guessing * Playlists guessing
*/ */
static mediamark_t **guess_pls_playlist (_lf_t *lf) { static void guess_pls_playlist (_lf_t *lf) {
mediamark_t **mmk = NULL;
if (!strcasecmp (lf->ext, "pls")) { if (!strcasecmp (lf->ext, "pls")) {
if (_lf_split_lines (lf)) { if (_lf_split_lines (lf)) {
int valid_pls = 0; int valid_pls = 0;
int entries_pls = 0; int entries_pls = 0;
int found_nument = 0; int found_nument = 0;
int stored_nument = 0; int stored_nument = 0;
int pl_line = 0; int pl_line = 0;
int linen = 0; uint32_t linen = 0;
int count = 0; int count = 0;
char *origin; mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
const char *store_mrl, *ln;
char buffer[_PATH_MAX + _NAME_MAX + 2];
origin = get_basedir (lf->filename);
do { do {
while ((ln = lf->lines[linen++]) != NULL) { while (linen < lf->num_lines) {
const char *ln = lf->lines[linen++];
if (valid_pls) { if (valid_pls) {
if (entries_pls) { if (entries_pls) {
int entry; int entry;
if ((!strncasecmp (ln, "file", 4)) && (( sscanf(ln + 4, "%d=", &en try)) == 1)) { if ((!strncasecmp (ln, "file", 4)) && (( sscanf(ln + 4, "%d=", &en try)) == 1)) {
char *mrl = strchr (ln, '='); char *mrl = strchr (ln, '=');
if (mrl) if (mrl && (entry > 0) && (entry <= entries_pls)) {
mrl++; m.mrl = mrl + 1;
if ((entry && mrl) && ((entry) <= entries_pls) && (mmk && (!mmk[ m.ident = NULL;
entry - 1]))) { stored_nument += _lf_add (lf, entry - 1, &m);
stored_nument++;
store_mrl = concat_basedir (buffer, sizeof (buffer), origin, m
rl);
mediamark_store_mmk (&mmk[(entry - 1)], store_mrl, NULL, NULL,
0, -1, 0, 0);
} }
} }
} else { } else {
if ((!strncasecmp (ln, "numberofentries", 15)) && ((sscanf (ln + 1 5, "=%d", &entries_pls)) == 1)) { if ((!strncasecmp (ln, "numberofentries", 15)) && ((sscanf (ln + 1 5, "=%d", &entries_pls)) == 1)) {
if (!found_nument) { if (!found_nument) {
if (entries_pls) { if (entries_pls) {
lf->num_entries = entries_pls; lf->num_entries = entries_pls;
mmk = (mediamark_t **) calloc ((entries_pls + 1), sizeof (me diamark_t *));
found_nument = 1; found_nument = 1;
} }
} }
} }
} }
} else if ((!strcasecmp (ln, "[playlist]"))) { } else if ((!strcasecmp (ln, "[playlist]"))) {
if (!valid_pls) { if (!valid_pls) {
valid_pls = 1; valid_pls = 1;
pl_line = linen; pl_line = linen;
} }
} }
} }
count++; count++;
linen = pl_line; linen = pl_line;
} while ((lf->num_entries && !stored_nument) && (count < 2)); } while ((lf->num_entries && !stored_nument) && (count < 2));
free (origin);
if (mmk && valid_pls && entries_pls) { if (lf->mmk && valid_pls && entries_pls) {
int i; int i;
mmk[entries_pls] = NULL;
/* Fill missing entries */ /* Fill missing entries */
m.mrl = NULL;
m.ident = _("!!Invalid entry!!");
for (i = 0; i < entries_pls; i++) { for (i = 0; i < entries_pls; i++) {
if (!mmk[i]) if (!lf->mmk[i])
mediamark_store_mmk (&mmk[i], _("!!Invalid entry!!"), NULL, NULL, 0, _lf_add (lf, i, &m);
-1, 0, 0);
} }
lf->type = "PLS"; lf->type = "PLS";
} }
if (valid_pls && entries_pls) if (valid_pls && entries_pls)
return mmk; return;
} }
} }
return NULL;
} }
static mediamark_t **guess_m3u_playlist (_lf_t *lf) { static void guess_m3u_playlist (_lf_t *lf) {
mediamark_t **mmk = NULL;
if (_lf_split_lines (lf)) { if (_lf_split_lines (lf)) {
int valid_m3u = 0; int valid_m3u = 0;
int entries_m3u = 0; int entries_m3u = 0;
char *title = NULL; char *title = NULL;
char *origin; uint32_t linen = 0;
int linen = 0; mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
const char *ln;
while (linen < lf->num_lines) {
char *ln = lf->lines[linen++];
origin = get_basedir (lf->filename);
while ((ln = lf->lines[linen++]) != NULL) {
if (valid_m3u) { if (valid_m3u) {
if (!strncmp (ln, "#EXTINF", 7)) { if (!strncmp (ln, "#EXTINF", 7)) {
char *ptitle; char *ptitle = strchr (ln, ',');
if ((ptitle = strchr (ln, ',')) != NULL) { title = ptitle ? ptitle + 1 : NULL;
ptitle++;
SAFE_FREE (title);
if (ptitle[0])
title = strdup (ptitle);
}
} else if (ln[0] != '#') { } else if (ln[0] != '#') {
char buffer[_PATH_MAX + _NAME_MAX + 2]; m.mrl = ln;
const char *entry; m.ident = title;
_lf_add (lf, entries_m3u, &m);
mmk = (mediamark_t **) realloc(mmk, sizeof(mediamark_t *) * (entries_m
3u + 2));
entry = concat_basedir(buffer, sizeof(buffer), origin, ln);
mediamark_store_mmk(&mmk[entries_m3u], entry, title, NULL, 0, -1, 0, 0
);
lf->num_entries = ++entries_m3u; lf->num_entries = ++entries_m3u;
title = NULL;
SAFE_FREE (title);
} }
} else if ((!strcasecmp (ln, "#EXTM3U"))) } else if ((!strcasecmp (ln, "#EXTM3U")))
valid_m3u = 1; valid_m3u = 1;
} }
if (valid_m3u && entries_m3u) { if (valid_m3u && entries_m3u) {
mmk[entries_m3u] = NULL;
lf->type = "M3U"; lf->type = "M3U";
} }
free (origin);
free (title);
} }
return mmk;
} }
static mediamark_t **guess_sfv_playlist (_lf_t *lf) { static void guess_sfv_playlist (_lf_t *lf) {
mediamark_t **mmk = NULL;
if (!strcasecmp (lf->ext, "sfv")) { if (!strcasecmp (lf->ext, "sfv")) {
if (_lf_split_lines (lf)) { if (_lf_split_lines (lf)) {
int valid_sfv = 0; int valid_sfv = 0;
int entries_sfv = 0; int entries_sfv = 0;
char *origin; uint32_t linen = 0;
int linen = 0; mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
char *ln;
origin = get_basedir (lf->filename); while (linen < lf->num_lines) {
while ((ln = lf->lines[linen++]) != NULL) { char *ln = lf->lines[linen++];
if (valid_sfv) {
if (strncmp (ln, ";", 1)) {
char buffer[_PATH_MAX + _NAME_MAX + 2];
const char *entry;
if (valid_sfv) {
if (ln[0] != ';') {
if (ln[0]) { if (ln[0]) {
long long int crc = 0; long long int crc = 0;
char *p = ln + strlen (ln) - 1, *q = NULL; char *p = lf->lines[linen] - 2, *q = NULL;
while ((p > ln) && (*p != ' ')) while ((p > ln) && (*p != ' '))
p--; p--;
if (p > ln) { if (p > ln) {
q = p; q = p;
*p = '\0'; *p = '\0';
p++; p++;
} }
if (p[0]) { if (p[0]) {
errno = 0; errno = 0;
crc = strtoll (p, &p, 16); crc = strtoll (p, &p, 16);
if ((errno == ERANGE) || (errno == EINVAL)) if ((errno == ERANGE) || (errno == EINVAL))
crc = 0; crc = 0;
} }
if (crc > 0) { if (crc > 0) {
mmk = (mediamark_t **) realloc(mmk, sizeof(mediamark_t *) * (ent m.mrl = ln;
ries_sfv + 2)); m.ident = NULL;
entry = concat_basedir(buffer, sizeof(buffer), origin, ln); _lf_add (lf, entries_sfv, &m);
mediamark_store_mmk(&mmk[entries_sfv], entry, NULL, NULL, 0, -1,
0, 0);
lf->num_entries = ++entries_sfv; lf->num_entries = ++entries_sfv;
} }
if (q) if (q)
*q = ' '; *q = ' ';
} }
} }
} else if (strlen(ln) > 1) { } else if (ln[0] && ln[1]) {
long int size; long int size;
int h, m, s; int h, m, s;
int Y, M, D; int Y, M, D;
char fn[2]; char fn[2];
char mon[4]; char mon[4];
if (((sscanf (ln, ";%ld %d:%d.%d %d-%d-%d %1s", &size, &h, &m, &s, &Y, &M, &D, &fn[0])) == 8) || if (((sscanf (ln, ";%ld %d:%d.%d %d-%d-%d %1s", &size, &h, &m, &s, &Y, &M, &D, &fn[0])) == 8) ||
((sscanf (ln, ";%ld %3s %d %d:%d:%d %d %1s", &size, &mon[0], &D, & h, &m, &s, &Y, &fn[0])) == 8)) ((sscanf (ln, ";%ld %3s %d %d:%d:%d %d %1s", &size, &mon[0], &D, & h, &m, &s, &Y, &fn[0])) == 8))
valid_sfv = 1; valid_sfv = 1;
} }
} }
if (valid_sfv && entries_sfv) { if (valid_sfv && entries_sfv) {
mmk[entries_sfv] = NULL;
lf->type = "SFV"; lf->type = "SFV";
} }
free (origin);
} }
} }
return mmk;
} }
static mediamark_t **guess_raw_playlist (_lf_t *lf) { static void guess_raw_playlist (_lf_t *lf) {
mediamark_t **mmk = NULL;
if (_lf_split_lines (lf)) { if (_lf_split_lines (lf)) {
char *origin;
int entries_raw = 0; int entries_raw = 0;
int linen = 0; uint32_t linen = 0;
const char *ln; mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
origin = get_basedir (lf->filename); while (linen < lf->num_lines) {
while ((ln = lf->lines[linen++]) != NULL) { char *ln = lf->lines[linen++];
if ((strncmp (ln, ";", 1)) && (strncmp (ln, "#", 1))) {
char buffer[_PATH_MAX + _NAME_MAX + 2];
const char *entry;
mmk = (mediamark_t **) realloc(mmk, sizeof(mediamark_t *) * (entries_raw if ((strncmp (ln, ";", 1)) && (strncmp (ln, "#", 1))) {
+ 2)); m.mrl = ln;
entry = concat_basedir(buffer, sizeof(buffer), origin, ln); m.ident = NULL;
mediamark_store_mmk(&mmk[entries_raw], entry, NULL, NULL, 0, -1, 0, 0); _lf_add (lf, entries_raw, &m);
lf->num_entries = ++entries_raw; lf->num_entries = ++entries_raw;
} }
} }
if (entries_raw) { if (entries_raw) {
mmk[entries_raw] = NULL;
lf->type = "RAW"; lf->type = "RAW";
} }
free (origin);
} }
return mmk;
} }
static mediamark_t **guess_toxine_playlist (_lf_t *lf) { static void guess_toxine_playlist (_lf_t *lf) {
mediamark_t **mmk = NULL; char *text = _lf_dup (lf);
char *origin; xitk_cfg_parse_t *tree = xitk_cfg_parse (text, XITK_CFG_PARSE_DEBUG);
int entries_tox = 0; xitk_cfg_parse_t *entry;
int num_entries;
{ if (!tree)
char *text = _lf_dup (lf); return;
xitk_cfg_parse_t *tree = xitk_cfg_parse (text, XITK_CFG_PARSE_DEBUG);
origin = get_basedir (lf->filename); /* just avoid reallocations. */
num_entries = 0;
if (tree && origin) { for (entry = tree + tree->first_child; entry != tree; entry = tree + entry->ne
xitk_cfg_parse_t *entry; xt)
int num_entries = 0; if ((entry->klen == 5) && !memcmp (text + entry->key, "entry", 5))
num_entries += 1;
for (entry = tree->first_child ? tree + tree->first_child : NULL; _lf_add (lf, num_entries, NULL);
entry; entry = entry->next ? tree + entry->next : NULL)
if ((entry->key >= 0) && !strcmp (text + entry->key, "entry")) num_entries = 0;
num_entries += 1; for (entry = tree + tree->first_child; entry != tree; entry = tree + entry->ne
mmk = malloc (sizeof (*mmk) * (num_entries + 2)); xt) {
if ((entry->klen == 5) && !memcmp (text + entry->key, "entry", 5)) {
for (entry = tree->first_child ? tree + tree->first_child : NULL; mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
entry; entry = entry->next ? tree + entry->next : NULL) { xitk_cfg_parse_t *elem;
if ((entry->key >= 0) && !strcmp (text + entry->key, "entry")) { uint32_t mmkf_members = 0;
xitk_cfg_parse_t *elem;
char path[_PATH_MAX + _NAME_MAX + 2]; for (elem = tree + entry->first_child; elem != tree; elem = tree + elem->n
mediamark_t mmkf; ext) {
int mmkf_members; const char *key = text + elem->key;
const char *val = text + elem->value;
mmkf.ident = NULL;
mmkf.sub = NULL; switch (elem->klen) {
mmkf.start = 0; case 3:
mmkf.end = -1; if (!memcmp (key, "end", 3)) {
mmkf.av_offset = 0; if (mmkf_members & 1)
mmkf.spu_offset = 0; break;
mmkf.mrl = NULL; mmkf_members |= 1;
mmkf_members = 0; /* ident, mrl, start, end, av offset, spu offset m.end = xitk_str2int32 (&val);
, sub */ } else if (!memcmp (key, "mrl", 3)) {
if (m.mrl)
for (elem = entry->first_child ? tree + entry->first_child : NULL; break;
elem; elem = elem->next ? tree + elem->next : NULL) { m.mrl = (char *)val;
const char *key = elem->key >= 0 ? text + elem->key : "";
const char *val = elem->value >= 0 ? text + elem->value : path;
path[0] = 0;
if (!strcmp (key, "identifier")) {
if (!(mmkf_members & 0x01)) {
mmkf_members |= 0x01;
mmkf.ident = strdup (val);
}
} else if (!strcmp (key, "subtitle")) {
if (!(mmkf_members & 0x40)) {
/* Workaround old toxine playlist version bug */
if (strcmp (val, "(null)")) {
mmkf_members |= 0x40;
mmkf.sub = strdup (concat_basedir (path, sizeof (path), origin
, val));
}
}
} else if (!strcmp (key, "spu_offset")) {
if (!(mmkf_members & 0x20)) {
mmkf_members |= 0x20;
mmkf.spu_offset = xitk_str2int32 (&val);
}
} else if (!strcmp (key, "av_offset")) {
if (!(mmkf_members & 0x10)) {
mmkf_members |= 0x10;
mmkf.av_offset = xitk_str2int32 (&val);
}
} else if (!strcmp (key, "start")) {
if (!(mmkf_members & 0x04)) {
mmkf_members |= 0x04;
mmkf.start = xitk_str2int32 (&val);
}
} else if (!strcmp (key, "end")) {
if (!(mmkf_members & 0x08)) {
mmkf_members |= 0x08;
mmkf.end = xitk_str2int32 (&val);
}
} else if (!strcmp (key, "mrl")) {
if (!(mmkf_members & 0x02)) {
mmkf_members |= 0x02;
mmkf.mrl = strdup (concat_basedir (path, sizeof (path), origin,
val));
}
} }
} break;
#if 0 case 5:
printf ("DUMP mediamark entry:\n"); if (!memcmp (key, "start", 5)) {
printf ("ident: '%s'\n", mmkf.ident); if (mmkf_members & 2)
printf ("mrl: '%s'\n", mmkf.mrl); break;
printf ("sub: '%s'\n", mmkf.sub); mmkf_members |= 2;
printf ("start: %d\n", mmkf.start); m.start = xitk_str2int32 (&val);
printf ("end: %d\n", mmkf.end); }
printf ("av_offset: %d\n", mmkf.av_offset); break;
printf ("spu_offset: %d\n", mmkf.spu_offset); case 8:
#endif if (!memcmp (key, "subtitle", 8)) {
if ((mmkf_members & 0x02) && mmk) { /* Workaround old toxine playlist version bug */
if (!(mmkf_members & 0x01)) if (m.sub || !strcmp (val, "(null)"))
mmkf.ident = mmkf.mrl; break;
mediamark_store_mmk (&mmk[entries_tox], mmkf.mrl, mmkf.ident, mmkf.s m.sub = (char *)val;
ub, }
mmkf.start, mmkf.end, mmkf.av_offset, mmkf.spu_offset); break;
lf->num_entries = ++entries_tox; case 9:
} if (!memcmp (key, "av_offset", 9)) {
if (mmkf_members & 0x01) if (mmkf_members & 4)
free (mmkf.ident); break;
free (mmkf.sub); mmkf_members |= 4;
free (mmkf.mrl); m.av_offset = xitk_str2int32 (&val);
}
break;
case 10:
if (!memcmp (key, "identifier", 10)) {
if (m.ident)
break;
m.ident = (char *)val; /** << will not be written to. */
} else if (!memcmp (key, "spu_offset", 10)) {
if (mmkf_members & 8)
break;
mmkf_members |= 8;
m.spu_offset = xitk_str2int32 (&val);
}
break;
default: ;
} }
} }
if (!m.mrl)
continue;
_lf_add (lf, num_entries, &m);
lf->num_entries = ++num_entries;
} }
free (origin);
xitk_cfg_unparse (tree);
} }
if (mmk && entries_tox) { xitk_cfg_unparse (tree);
mmk[entries_tox] = NULL; if (num_entries)
lf->type = "TOX"; lf->type = "TOX";
return mmk;
}
free (mmk);
return NULL;
} }
/* /*
* XML based playlists * XML based playlists
*/ */
static mediamark_t **xml_asx_playlist (_lf_t *lf, xml_node_t *xml_tree) { static void xml_asx_playlist (_lf_t *lf, xml_node_t *xml_tree) {
mediamark_t **mmk = NULL; int entries_asx = 0;
if(xml_tree) { if (!strcasecmp (xml_tree->name, "ASX")) {
xml_node_t *asx_entry, *asx_ref; mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
xml_property_t *asx_prop; xml_property_t *asx_prop;
int entries_asx = 0; int version_ok = 0;
if(!strcasecmp(xml_tree->name, "ASX")) {
asx_prop = xml_tree->props;
while((asx_prop) && (strcasecmp(asx_prop->name, "VERSION")))
asx_prop = asx_prop->next;
if(asx_prop) {
int version_major, version_minor = 0;
if((((sscanf(asx_prop->value, "%d.%d", &version_major, &version_minor)) =
= 2) ||
((sscanf(asx_prop->value, "%d", &version_major)) == 1)) &&
((version_major == 3) && (version_minor == 0))) {
__parse_anyway:
asx_entry = xml_tree->child;
while(asx_entry) {
if((!strcasecmp(asx_entry->name, "ENTRY")) ||
(!strcasecmp(asx_entry->name, "ENTRYREF"))) {
char *title = NULL;
char *href = NULL;
char *author = NULL;
char *sub = NULL;
asx_ref = asx_entry->child;
while(asx_ref) {
if(!strcasecmp(asx_ref->name, "TITLE")) {
if(!title)
title = asx_ref->data;
}
else if(!strcasecmp(asx_ref->name, "AUTHOR")) {
if(!author)
author = asx_ref->data;
}
else if(!strcasecmp(asx_ref->name, "REF")) {
for(asx_prop = asx_ref->props; asx_prop; asx_prop = asx_prop->n
ext) {
if(!strcasecmp(asx_prop->name, "HREF")) {
if(!href)
href = asx_prop->value;
}
/* This is not part of the ASX specs */
else if(!strcasecmp(asx_prop->name, "SUBTITLE")) {
if(!sub)
sub = asx_prop->value;
}
if(href && sub)
break;
}
}
asx_ref = asx_ref->next;
}
if (href && href[0]) {
char *atitle = NULL;
char *aauthor = NULL;
char *real_title = NULL;
int len = 0;
if (title && title[0]) {
atitle = strdup (title);
len = str_unquote (atitle);
if (author && author[0]) {
aauthor = strdup (author);
len += str_unquote (aauthor) + 3;
}
len++;
}
if(atitle && strlen(atitle)) {
real_title = (char *) malloc(len);
strcpy(real_title, atitle);
if(aauthor && strlen(aauthor))
snprintf(real_title+strlen(real_title), len-strlen(real_title
), " (%s)", aauthor);
}
mmk = (mediamark_t **) realloc(mmk, sizeof(mediamark_t *) * (entr
ies_asx + 2));
mediamark_store_mmk(&mmk[entries_asx], href, real_title, sub, 0,
-1, 0, 0);
lf->num_entries = ++entries_asx;
SAFE_FREE(real_title);
SAFE_FREE (atitle);
SAFE_FREE (aauthor);
}
href = title = author = NULL;
}
asx_entry = asx_entry->next;
}
}
else
fprintf(stderr, "%s(): Wrong ASX version: %s\n", __XINE_FUNCTION__, asx
_prop->value);
for (asx_prop = xml_tree->props; asx_prop && strcasecmp (asx_prop->name, "VE
RSION"); asx_prop = asx_prop->next) ;
if (asx_prop) {
int version_major, version_minor = 0;
if ((((sscanf (asx_prop->value, "%d.%d", &version_major, &version_minor))
== 2) ||
((sscanf (asx_prop->value, "%d", &version_major)) == 1)) &&
((version_major == 3) && (version_minor == 0))) {
version_ok = 1;
} else {
fprintf (stderr, "%s(): Wrong ASX version: %s\n", __XINE_FUNCTION__, asx
_prop->value);
} }
else { } else {
fprintf(stderr, "%s(): Unable to find VERSION tag.\n", __XINE_FUNCTION__) fprintf (stderr, "%s(): Unable to find VERSION tag.\n", __XINE_FUNCTION__)
; ;
fprintf(stderr, "%s(): last chance: try to parse it anyway\n", __XINE_FUN fprintf (stderr, "%s(): last chance: try to parse it anyway\n", __XINE_FUN
CTION__); CTION__);
goto __parse_anyway; version_ok = 2;
} }
} if (version_ok) {
#ifdef DEBUG xml_node_t *asx_entry;
else
fprintf(stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, for (asx_entry = xml_tree->child; asx_entry; asx_entry = asx_entry->next)
xml_tree->name); {
#endif if (!strcasecmp (asx_entry->name, "ENTRY") ||
!strcasecmp (asx_entry->name, "ENTRYREF")) {
char *title = NULL, *href = NULL, *author = NULL, *sub = NULL;
char *atitle = NULL, *aauthor = NULL, *real_title = NULL;
xml_node_t *asx_ref;
int len = 0;
for (asx_ref = asx_entry->child; asx_ref; asx_ref = asx_ref->next) {
if (!strcasecmp (asx_ref->name, "TITLE")) {
if (!title)
title = asx_ref->data;
} else if (!strcasecmp (asx_ref->name, "AUTHOR")) {
if (!author)
author = asx_ref->data;
} else if (!strcasecmp (asx_ref->name, "REF")) {
for (asx_prop = asx_ref->props; asx_prop; asx_prop = asx_prop->nex
t) {
if (!strcasecmp (asx_prop->name, "HREF")) {
if (!href)
href = asx_prop->value;
} else if (!strcasecmp (asx_prop->name, "SUBTITLE")) {
/* This is not part of the ASX specs */
if (!sub)
sub = asx_prop->value;
}
if (href && sub)
break;
}
}
}
if (href && href[0]) {
if (title && title[0]) {
atitle = strdup (title);
len = str_unquote (atitle);
}
if (author && author[0]) {
aauthor = strdup (author);
len += str_unquote (aauthor) + 3;
}
len++;
}
if (atitle && atitle[0]) {
real_title = malloc (len);
strcpy (real_title, atitle);
if (aauthor && aauthor[0]) {
int rtl = xitk_find_byte (real_title, 0);
/* Maybe it's 'ASF <url> */ snprintf (real_title + rtl, len - rtl, " (%s)", aauthor);
if (entries_asx == 0) {
if (_lf_split_lines (lf)) {
int linen = 0;
const char *ln;
while ((ln = lf->lines[linen++]) != NULL) {
if (!strncasecmp ("ASF", ln, 3)) {
const char *p = ln + 3;
while (p && ((*p == ' ') || (*p == '\t')))
p++;
if (p && p[0]) {
mmk = (mediamark_t **) realloc(mmk, sizeof(mediamark_t *) * (entri
es_asx + 2));
mediamark_store_mmk(&mmk[entries_asx], p, p, NULL, 0, -1, 0, 0);
lf->num_entries = ++entries_asx;
} }
} }
m.mrl = href;
m.ident = real_title;
m.sub = sub;
_lf_add (lf, entries_asx, &m);
lf->num_entries = ++entries_asx;
SAFE_FREE (real_title);
SAFE_FREE (atitle);
SAFE_FREE (aauthor);
} }
} }
} }
if (entries_asx) {
mmk[entries_asx] = NULL;
lf->type = "ASX3";
return mmk;
}
} }
#ifdef DEBUG
else
fprintf (stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, x
ml_tree->name);
#endif
return NULL; /* Maybe it's 'ASF <url> */
} if (entries_asx == 0) {
if (_lf_split_lines (lf)) {
static void __gx_get_entries (_lf_t *lf, mediamark_t ***mmk, int *entries, xml_n uint32_t linen = 0;
ode_t *entry) { mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
xml_property_t *prop;
xml_node_t *ref;
xml_node_t *node = entry;
while(node) {
if(!strcasecmp(node->name, "SUB"))
__gx_get_entries (lf, mmk, entries, node->child);
else if(!strcasecmp(node->name, "ENTRY")) {
char *title = NULL;
char *href = NULL;
int start = 0;
ref = node->child;
while(ref) {
if(!strcasecmp(ref->name, "TITLE")) {
if(!title)
title = ref->data;
}
else if(!strcasecmp(ref->name, "REF")) {
for(prop = ref->props; prop; prop = prop->next) {
if(!strcasecmp(prop->name, "HREF")) {
if(!href)
href = prop->value;
}
if(href)
break;
}
}
else if(!strcasecmp(ref->name, "TIME")) {
for(prop = ref->props; prop; prop = prop->next) {
if(!strcasecmp(prop->name, "START")) {
if(prop->value && strlen(prop->value)) while (linen < lf->num_lines) {
start = atoi(prop->value); char *ln = lf->lines[linen++];
} if (!strncasecmp ("ASF", ln, 3)) {
} char *p = ln + 3;
}
ref = ref->next; while ((*p == ' ') || (*p == '\t'))
p++;
if (p[0]) {
m.mrl = p;
m.ident = NULL;
_lf_add (lf, entries_asx, &m);
lf->num_entries = ++entries_asx;
}
}
} }
}
}
if (entries_asx)
lf->type = "ASX3";
}
if(href && strlen(href)) { static void __gx_get_entries (_lf_t *lf, int *entries, xml_node_t *entry) {
char *atitle = NULL; xml_node_t *node;
mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
if (title && title[0]) {
atitle = strdup(title); for (node = entry; node; node = node->next) {
str_unquote (atitle); if (!strcasecmp (node->name, "SUB")) {
} __gx_get_entries (lf, entries, node->child);
} else if (!strcasecmp (node->name, "ENTRY")) {
xml_node_t *ref;
m.ident = NULL;
m.mrl = NULL;
m.start = 0;
for (ref = node->child; ref; ref = ref->next) {
if (!strcasecmp (ref->name, "TITLE")) {
if (!m.ident)
m.ident = ref->data;
} else if (!strcasecmp (ref->name, "REF")) {
xml_property_t *prop;
for (prop = ref->props; prop; prop = prop->next) {
if (!strcasecmp (prop->name, "HREF")) {
if (!m.mrl) {
m.mrl = prop->value;
if (m.mrl)
break;
}
}
}
} else if (!strcasecmp (ref->name, "TIME")) {
xml_property_t *prop;
(*mmk) = (mediamark_t **) realloc((*mmk), sizeof(mediamark_t *) * (*entri for (prop = ref->props; prop; prop = prop->next) {
es + 2)); if (!strcasecmp (prop->name, "START")) {
if (prop->value && prop->value[0])
m.start = atoi (prop->value);
}
}
}
}
mediamark_store_mmk (&(*mmk)[*entries], href, (atitle && atitle[0]) ? at if (m.mrl && m.mrl[0]) {
itle : NULL, NULL, start, -1, 0, 0); if (m.ident && m.ident[0]) {
m.ident = strdup (m.ident);
str_unquote (m.ident);
} else {
m.ident = NULL;
}
_lf_add (lf, *entries, &m);
lf->num_entries = ++(*entries); lf->num_entries = ++(*entries);
SAFE_FREE (m.ident);
free(atitle);
} }
href = title = NULL;
start = 0;
} }
node = node->next;
} }
} }
static mediamark_t **xml_gx_playlist (_lf_t *lf, xml_node_t *xml_tree) { static void xml_gx_playlist (_lf_t *lf, xml_node_t *xml_tree) {
mediamark_t **mmk = NULL; int entries_gx = 0;
if(xml_tree) {
xml_node_t *gx_entry;
xml_property_t *gx_prop;
int entries_gx = 0;
if(!strcasecmp(xml_tree->name, "GXINEMM")) { if (!strcasecmp (xml_tree->name, "GXINEMM")) {
xml_property_t *gx_prop;
gx_prop = xml_tree->props; for (gx_prop = xml_tree->props; gx_prop && strcasecmp (gx_prop->name, "VERSI
ON"); gx_prop = gx_prop->next) ;
if (gx_prop) {
int version_major;
while((gx_prop) && (strcasecmp(gx_prop->name, "VERSION"))) if (((sscanf (gx_prop->value, "%d", &version_major)) == 1) && (version_maj
gx_prop = gx_prop->next; or == 1)) {
xml_node_t *gx_entry;
if(gx_prop) { for (gx_entry = xml_tree->child; gx_entry; gx_entry = gx_entry->next) {
int version_major; if (!strcasecmp (gx_entry->name, "SUB")) {
__gx_get_entries (lf, &entries_gx, gx_entry->child);
if(((sscanf(gx_prop->value, "%d", &version_major)) == 1) && (version_majo } else if (!strcasecmp (gx_entry->name, "ENTRY")) {
r == 1)) { __gx_get_entries (lf, &entries_gx, gx_entry);
}
gx_entry = xml_tree->child; }
while(gx_entry) { } else {
fprintf (stderr, "%s(): Wrong GXINEMM version: %s\n", __XINE_FUNCTION__,
if(!strcasecmp(gx_entry->name, "SUB")) { gx_prop->value);
__gx_get_entries (lf, &mmk, &entries_gx, gx_entry->child);
}
else if(!strcasecmp(gx_entry->name, "ENTRY"))
__gx_get_entries (lf, &mmk, &entries_gx, gx_entry);
gx_entry = gx_entry->next;
}
}
else
fprintf(stderr, "%s(): Wrong GXINEMM version: %s\n", __XINE_FUNCTION__,
gx_prop->value);
} }
else } else {
fprintf(stderr, "%s(): Unable to find VERSION tag.\n", __XINE_FUNCTION__) fprintf (stderr, "%s(): Unable to find VERSION tag.\n", __XINE_FUNCTION__)
; ;
} }
}
#ifdef DEBUG #ifdef DEBUG
else else
fprintf(stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, fprintf (stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, x
xml_tree->name); ml_tree->name);
#endif #endif
if (entries_gx)
if(entries_gx) { lf->type = "GXMM";
mmk[entries_gx] = NULL;
lf->type = "GXMM";
return mmk;
}
}
return NULL;
} }
static mediamark_t **xml_noatun_playlist (_lf_t *lf, xml_node_t *xml_tree) { static void xml_noatun_playlist (_lf_t *lf, xml_node_t *xml_tree) {
mediamark_t **mmk = NULL; int entries_noa = 0;
if(xml_tree) {
xml_node_t *noa_entry;
xml_property_t *noa_prop;
int entries_noa = 0;
if(!strcasecmp(xml_tree->name, "PLAYLIST")) { if (!strcasecmp (xml_tree->name, "PLAYLIST")) {
int found = 0; mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
xml_property_t *noa_prop;
int found = 0;
noa_prop = xml_tree->props; for (noa_prop = xml_tree->props; noa_prop; noa_prop = noa_prop->next) {
if (!strcasecmp (noa_prop->name, "CLIENT") && strcasecmp (noa_prop->value,
while(noa_prop) { "NOATUN")) {
if((!strcasecmp(noa_prop->name, "CLIENT")) && (!strcasecmp(noa_prop->valu found++;
e, "NOATUN"))) } else if (!strcasecmp (noa_prop->name, "VERSION")) {
found++; int version_major;
else if(!strcasecmp(noa_prop->name, "VERSION")) {
int version_major;
if(((sscanf(noa_prop->value, "%d", &version_major)) == 1) && (version_m
ajor == 1))
found++;
}
noa_prop = noa_prop->next; if (((sscanf (noa_prop->value, "%d", &version_major)) == 1) && (version_
major == 1))
found++;
} }
}
if(found >= 2) { if (found >= 2) {
noa_entry = xml_tree->child; xml_node_t *noa_entry;
while(noa_entry) {
if(!strcasecmp(noa_entry->name, "ITEM")) {
char *real_title = NULL;
char *title = NULL;
char *album = NULL;
char *artist = NULL;
char *url = NULL;
for(noa_prop = noa_entry->props; noa_prop; noa_prop = noa_prop->next)
{
if(!strcasecmp(noa_prop->name, "TITLE"))
title = noa_prop->value;
else if(!strcasecmp(noa_prop->name, "ALBUM"))
album = noa_prop->value;
else if(!strcasecmp(noa_prop->name, "ARTIST"))
artist = noa_prop->value;
else if(!strcasecmp(noa_prop->name, "URL"))
url = noa_prop->value;
}
if(url) {
/*
title (artist - album)
*/
if(title && title[0]) {
if(artist && artist[0] && album && album[0]) {
real_title = xitk_asprintf("%s (%s - %s)", title, artist, albu
m);
}
else if(artist && artist[0]) {
real_title = xitk_asprintf("%s (%s)", title, artist);
}
else if(album && album[0]) {
real_title = xitk_asprintf("%s (%s)", title, album);
}
else
real_title = strdup(title);
}
mmk = (mediamark_t **) realloc(mmk, sizeof(mediamark_t *) * (entrie
s_noa + 2));
mediamark_store_mmk(&mmk[entries_noa], url, real_title, NULL, 0, -1
, 0, 0);
lf->num_entries = ++entries_noa;
free(real_title); for (noa_entry = xml_tree->child; noa_entry; noa_entry = noa_entry->next)
{
if (!strcasecmp (noa_entry->name, "ITEM")) {
char *title = NULL, *album = NULL, *artist = NULL, *url = NULL;
} for (noa_prop = noa_entry->props; noa_prop; noa_prop = noa_prop->next)
} {
if (!strcasecmp (noa_prop->name, "TITLE"))
noa_entry = noa_entry->next; title = noa_prop->value;
} else if (!strcasecmp (noa_prop->name, "ALBUM"))
album = noa_prop->value;
else if (!strcasecmp (noa_prop->name, "ARTIST"))
artist = noa_prop->value;
else if (!strcasecmp (noa_prop->name, "URL"))
url = noa_prop->value;
}
if (url) {
char *real_title = NULL;
/* title (artist - album) */
if (title && title[0]) {
if (artist && artist[0] && album && album[0]) {
real_title = xitk_asprintf ("%s (%s - %s)", title, artist, album
);
} else if (artist && artist[0]) {
real_title = xitk_asprintf ("%s (%s)", title, artist);
} else if (album && album[0]) {
real_title = xitk_asprintf ("%s (%s)", title, album);
} else {
real_title = strdup (title);
}
}
m.mrl = url;
m.ident = real_title;
_lf_add (lf, entries_noa, &m);
lf->num_entries = ++entries_noa;
free (real_title);
}
}
} }
} }
}
#ifdef DEBUG #ifdef DEBUG
else else
fprintf(stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, fprintf (stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, x
xml_tree->name); ml_tree->name);
#endif #endif
if (entries_noa)
if(entries_noa) { lf->type = "NOATUN";
mmk[entries_noa] = NULL;
lf->type = "NOATUN";
return mmk;
}
}
return NULL;
} }
/* /*
* ********************************** SMIL BEGIN ******************************* **** * ********************************** SMIL BEGIN ******************************* ****
*/ */
#undef DEBUG_SMIL #undef DEBUG_SMIL
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
static int offset = 0; static int offset = 0;
#define palign do { int i; for(i = 0; i < offset; i++) { printf(" "); } } while( 0) #define palign do { int i; for(i = 0; i < offset; i++) { printf(" "); } } while( 0)
skipping to change at line 1309 skipping to change at line 1826
char *year; char *year;
char *base; char *base;
/* End Header */ /* End Header */
smil_node_t *first; smil_node_t *first;
smil_node_t *node; smil_node_t *node;
} smil_t; } smil_t;
/* protos */ /* protos */
static void smil_seq(smil_t *, smil_node_t **, xml_node_t *, smil_property_t *); static void smil_par (smil_t *, smil_node_t **, xml_node_t *);
static void smil_par(smil_t *, smil_node_t **, xml_node_t *, smil_property_t *); static void smil_switch (smil_t *, smil_node_t **, xml_node_t *);
static void smil_switch(smil_t *, smil_node_t **, xml_node_t *, smil_property_t
*);
static void smil_repeat(int, smil_node_t *, smil_node_t **, smil_property_t *);
static void smil_init_smil_property(smil_property_t *sprop) { static void smil_init_smil_property(smil_property_t *sprop) {
sprop->anchor = NULL; sprop->anchor = NULL;
sprop->repeat = 1; sprop->repeat = 1;
sprop->begin = 0; sprop->begin = 0;
sprop->clip_begin = 0; sprop->clip_begin = 0;
sprop->end = -1; sprop->end = -1;
sprop->clip_end = -1; sprop->clip_end = -1;
sprop->duration = 0; sprop->duration = 0;
} }
skipping to change at line 1334 skipping to change at line 1849
smil_node_t *node; smil_node_t *node;
node = (smil_node_t *) calloc(1, sizeof(smil_node_t)); node = (smil_node_t *) calloc(1, sizeof(smil_node_t));
node->mmk = NULL; node->mmk = NULL;
node->next = NULL; node->next = NULL;
smil_init_smil_property(&(node->prop)); smil_init_smil_property(&(node->prop));
return node; return node;
} }
static mediamark_t *smil_new_mediamark(void) { static mediamark_t *smil_new_mediamark (void) {
mediamark_t *mmk; mediamark_t *mmk = calloc (1, sizeof (*mmk));
mmk = (mediamark_t *) calloc(1, sizeof(mediamark_t));
mmk->mrl = NULL;
mmk->ident = NULL;
mmk->sub = NULL;
mmk->start = 0;
mmk->end = -1;
mmk->played = 0;
mmk->alternates = NULL;
mmk->cur_alt = NULL;
if (mmk) {
mmk->end = -1;
mmk->from = MMK_FROM_PLAYLIST;
}
return mmk; return mmk;
} }
static mediamark_t *smil_duplicate_mmk(mediamark_t *ommk) { static mediamark_t *smil_duplicate_mmk(mediamark_t *ommk) {
mediamark_t *mmk = NULL; mediamark_t *mmk = NULL;
if(ommk) { if(ommk) {
mmk = smil_new_mediamark(); mmk = smil_new_mediamark();
mmk->mrl = strdup(ommk->mrl); mmk->mrl = strdup(ommk->mrl);
mmk->ident = strdup(ommk->ident ? ommk->ident : ommk->mrl); mmk->ident = strdup(ommk->ident ? ommk->ident : ommk->mrl);
mmk->sub = ommk->sub ? strdup(ommk->sub) : NULL; mmk->sub = ommk->sub ? strdup(ommk->sub) : NULL;
mmk->start = ommk->start; mmk->start = ommk->start;
mmk->end = ommk->end; mmk->end = ommk->end;
mmk->played = ommk->played; mmk->played = ommk->played;
mmk->type = ommk->type;
mmk->from = ommk->from;
mmk->alternates = NULL; mmk->alternates = NULL;
mmk->cur_alt = NULL; mmk->cur_alt = NULL;
} }
return mmk; return mmk;
} }
static void smil_free_properties(smil_property_t *smil_props) { static void smil_free_properties(smil_property_t *smil_props) {
if(smil_props) { if(smil_props) {
SAFE_FREE(smil_props->anchor); SAFE_FREE(smil_props->anchor);
} }
skipping to change at line 1562 skipping to change at line 2073
printf("HREF: %s\n", dprop->anchor); printf("HREF: %s\n", dprop->anchor);
#endif #endif
} }
} }
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset -= 2; offset -= 2;
#endif #endif
} }
static void smil_repeat (int times, smil_node_t *from, smil_node_t **snode) {
int i;
if(times > 1) {
smil_node_t *node, *to;
to = (*snode);
for(i = 0; i < (times - 1); i++) {
int found = 0;
node = from;
while(!found) {
smil_node_t *nnode = smil_new_node();
nnode->mmk = smil_duplicate_mmk(node->mmk);
(*snode)->next = nnode;
(*snode) = nnode;
if(node == to)
found = 1;
node = node->next;
}
}
}
else {
smil_node_t *nnode = smil_new_node();
(*snode)->next = nnode;
(*snode) = (*snode)->next;
}
}
static void smil_properties(smil_t *smil, smil_node_t **snode, static void smil_properties(smil_t *smil, smil_node_t **snode,
xml_property_t *props, smil_property_t *sprop) { xml_property_t *props, smil_property_t *sprop) {
xml_property_t *prop; xml_property_t *prop;
int gotmrl = 0; int gotmrl = 0;
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
#endif #endif
for(prop = props; prop; prop = prop->next) { for(prop = props; prop; prop = prop->next) {
skipping to change at line 1592 skipping to change at line 2139
if((*snode)->mmk == NULL) if((*snode)->mmk == NULL)
(*snode)->mmk = smil_new_mediamark(); (*snode)->mmk = smil_new_mediamark();
/* /*
handle BASE, ANCHOR handle BASE, ANCHOR
*/ */
if(sprop && sprop->anchor) if(sprop && sprop->anchor)
(*snode)->mmk->mrl = strdup(sprop->anchor); (*snode)->mmk->mrl = strdup(sprop->anchor);
else { else {
size_t l1 = smil->base ? strlen (smil->base) : 0, l2 = strlen (prop->v alue) + 1; size_t l1 = smil->base ? xitk_find_byte (smil->base, 0) : 0, l2 = xi tk_find_byte (prop->value, 0) + 1;
char *p = malloc (l1 + l2 + 1); char *p = malloc (l1 + l2 + 1);
(*snode)->mmk->mrl = p; (*snode)->mmk->mrl = p;
if (p) { if (p) {
if (l1 && !strstr (prop->value, "://")) { if (l1 && !strstr (prop->value, "://")) {
memcpy (p, smil->base, l1); p += l1; memcpy (p, smil->base, l1); p += l1;
if (p[-1] != '/') if (p[-1] != '/')
*p++ = '/'; *p++ = '/';
} }
memcpy (p, prop->value, l2); memcpy (p, prop->value, l2);
} }
skipping to change at line 1656 skipping to change at line 2203
printf("DURATION: %d\n", (*snode)->prop.duration); printf("DURATION: %d\n", (*snode)->prop.duration);
#endif #endif
} }
} }
} }
if(gotmrl) { if(gotmrl) {
smil_node_t *node = (*snode); smil_node_t *node = (*snode);
int repeat = node->prop.repeat; int repeat = node->prop.repeat;
if((*snode)->mmk->ident == NULL)
(*snode)->mmk->ident = strdup((*snode)->mmk->mrl);
if(sprop) { if(sprop) {
if(sprop->clip_begin && (node->prop.clip_begin == 0)) if(sprop->clip_begin && (node->prop.clip_begin == 0))
node->mmk->start = sprop->clip_begin; node->mmk->start = sprop->clip_begin;
else else
node->mmk->start = node->prop.clip_begin; node->mmk->start = node->prop.clip_begin;
if(sprop->clip_end && (node->prop.clip_end == -1)) if(sprop->clip_end && (node->prop.clip_end == -1))
node->mmk->end = sprop->clip_end; node->mmk->end = sprop->clip_end;
else else
node->mmk->end = node->prop.clip_end; node->mmk->end = node->prop.clip_end;
skipping to change at line 1683 skipping to change at line 2227
node->mmk->end = node->mmk->start + node->prop.duration; node->mmk->end = node->mmk->start + node->prop.duration;
} }
else { else {
node->mmk->start = node->prop.clip_begin; node->mmk->start = node->prop.clip_begin;
node->mmk->end = node->prop.clip_end; node->mmk->end = node->prop.clip_end;
if(node->prop.duration) if(node->prop.duration)
node->mmk->end = node->mmk->start + node->prop.duration; node->mmk->end = node->mmk->start + node->prop.duration;
} }
smil_repeat((repeat <= 1) ? 1 : repeat, node, snode, sprop); smil_repeat ((repeat <= 1) ? 1 : repeat, node, snode);
} }
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
palign; palign;
printf("---\n"); printf("---\n");
offset -= 2; offset -= 2;
#endif #endif
} }
static void smil_repeat(int times, smil_node_t *from,
smil_node_t **snode, smil_property_t *sprop) {
int i;
if(times > 1) {
smil_node_t *node, *to;
to = (*snode);
for(i = 0; i < (times - 1); i++) {
int found = 0;
node = from;
while(!found) {
smil_node_t *nnode = smil_new_node();
nnode->mmk = smil_duplicate_mmk(node->mmk);
(*snode)->next = nnode;
(*snode) = nnode;
if(node == to)
found = 1;
node = node->next;
}
}
}
else {
smil_node_t *nnode = smil_new_node();
(*snode)->next = nnode;
(*snode) = (*snode)->next;
}
}
/* /*
* Sequence playback * Sequence playback
*/ */
static void smil_seq(smil_t *smil, static void smil_seq (smil_t *smil, smil_node_t **snode, xml_node_t *node) {
smil_node_t **snode, xml_node_t *node, smil_property_t *spro
p) {
xml_node_t *seq; xml_node_t *seq;
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
#endif #endif
for(seq = node; seq; seq = seq->next) { for(seq = node; seq; seq = seq->next) {
if(!strcasecmp(seq->name, "SEQ")) { if(!strcasecmp(seq->name, "SEQ")) {
smil_property_t smil_props; smil_property_t smil_props;
skipping to change at line 1756 skipping to change at line 2263
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
palign; palign;
printf("seq NEW SEQ\n"); printf("seq NEW SEQ\n");
offset -= 2; offset -= 2;
#endif #endif
smil_get_properties(&smil_props, seq->props); smil_get_properties(&smil_props, seq->props);
smil_seq(smil, snode, seq->child, &smil_props); smil_seq(smil, snode, seq->child);
smil_repeat(smil_props.repeat, node, snode, &smil_props); smil_repeat (smil_props.repeat, node, snode);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if(!strcasecmp(seq->name, "PAR")) { else if(!strcasecmp(seq->name, "PAR")) {
smil_property_t smil_props; smil_property_t smil_props;
smil_node_t *node = (*snode); smil_node_t *node = (*snode);
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
palign; palign;
printf("seq NEW PAR\n"); printf("seq NEW PAR\n");
offset -= 2; offset -= 2;
#endif #endif
smil_get_properties(&smil_props, seq->props); smil_get_properties(&smil_props, seq->props);
smil_par(smil, snode, seq->child, &smil_props); smil_par (smil, snode, seq->child);
smil_repeat(smil_props.repeat, node, snode, &smil_props); smil_repeat (smil_props.repeat, node, snode);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if(!strcasecmp(seq->name, "SWITCH")) { else if(!strcasecmp(seq->name, "SWITCH")) {
smil_property_t smil_props; smil_property_t smil_props;
smil_node_t *node = (*snode); smil_node_t *node = (*snode);
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
palign; palign;
printf("seq NEW SWITCH\n"); printf("seq NEW SWITCH\n");
offset -= 2; offset -= 2;
#endif #endif
smil_get_properties(&smil_props, seq->props); smil_get_properties(&smil_props, seq->props);
smil_switch(smil, snode, seq->child, &smil_props); smil_switch (smil, snode, seq->child);
smil_repeat(smil_props.repeat, node, snode, &smil_props); smil_repeat (smil_props.repeat, node, snode);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if((!strcasecmp(seq->name, "VIDEO")) || else if((!strcasecmp(seq->name, "VIDEO")) ||
(!strcasecmp(seq->name, "AUDIO")) || (!strcasecmp(seq->name, "AUDIO")) ||
(!strcasecmp(seq->name, "A"))) { (!strcasecmp(seq->name, "A"))) {
smil_property_t smil_props; smil_property_t smil_props;
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
if(seq->child) { if(seq->child) {
skipping to change at line 1831 skipping to change at line 2338
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
} }
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset -= 2; offset -= 2;
#endif #endif
} }
/* /*
* Parallel playback * Parallel playback
*/ */
static void smil_par(smil_t *smil, smil_node_t **snode, xml_node_t *node, smil_p roperty_t *sprop) { static void smil_par (smil_t *smil, smil_node_t **snode, xml_node_t *node) {
xml_node_t *par; xml_node_t *par;
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
#endif #endif
for(par = node; par; par = par->next) { for(par = node; par; par = par->next) {
if(!strcasecmp(par->name, "SEQ")) { if(!strcasecmp(par->name, "SEQ")) {
smil_property_t smil_props; smil_property_t smil_props;
skipping to change at line 1854 skipping to change at line 2361
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
palign; palign;
printf("par NEW SEQ\n"); printf("par NEW SEQ\n");
offset -= 2; offset -= 2;
#endif #endif
smil_get_properties(&smil_props, par->props); smil_get_properties(&smil_props, par->props);
smil_seq(smil, snode, par->child, &smil_props); smil_seq(smil, snode, par->child);
smil_repeat(smil_props.repeat, node, snode, &smil_props); smil_repeat (smil_props.repeat, node, snode);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if(!strcasecmp(par->name, "PAR")) { else if(!strcasecmp(par->name, "PAR")) {
smil_property_t smil_props; smil_property_t smil_props;
smil_node_t *node = (*snode); smil_node_t *node = (*snode);
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
palign; palign;
printf("par NEW PAR\n"); printf("par NEW PAR\n");
offset -= 2; offset -= 2;
#endif #endif
smil_get_properties(&smil_props, par->props); smil_get_properties(&smil_props, par->props);
smil_par(smil, snode, par->child, &smil_props); smil_par (smil, snode, par->child);
smil_repeat(smil_props.repeat, node, snode, &smil_props); smil_repeat (smil_props.repeat, node, snode);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if(!strcasecmp(par->name, "SWITCH")) { else if(!strcasecmp(par->name, "SWITCH")) {
smil_property_t smil_props; smil_property_t smil_props;
smil_node_t *node = (*snode); smil_node_t *node = (*snode);
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
palign; palign;
printf("par NEW SWITCH\n"); printf("par NEW SWITCH\n");
offset -= 2; offset -= 2;
#endif #endif
smil_get_properties(&smil_props, par->props); smil_get_properties(&smil_props, par->props);
smil_switch(smil, snode, par->child, &smil_props); smil_switch (smil, snode, par->child);
smil_repeat(smil_props.repeat, node, snode, &smil_props); smil_repeat (smil_props.repeat, node, snode);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if((!strcasecmp(par->name, "VIDEO")) || else if((!strcasecmp(par->name, "VIDEO")) ||
(!strcasecmp(par->name, "AUDIO")) || (!strcasecmp(par->name, "AUDIO")) ||
(!strcasecmp(par->name, "A"))) { (!strcasecmp(par->name, "A"))) {
smil_property_t smil_props; smil_property_t smil_props;
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
if(par->child) { if(par->child) {
skipping to change at line 1925 skipping to change at line 2432
smil_properties(smil, snode, par->props, &smil_props); smil_properties(smil, snode, par->props, &smil_props);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
} }
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset -= 2; offset -= 2;
#endif #endif
} }
static void smil_switch(smil_t *smil, smil_node_t **snode, xml_node_t *node, smi l_property_t *sprop) { static void smil_switch (smil_t *smil, smil_node_t **snode, xml_node_t *node) {
xml_node_t *nswitch; xml_node_t *nswitch;
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
#endif #endif
for(nswitch = node; nswitch; nswitch = nswitch->next) { for(nswitch = node; nswitch; nswitch = nswitch->next) {
if(!strcasecmp(nswitch->name, "SEQ")) { if(!strcasecmp(nswitch->name, "SEQ")) {
smil_property_t smil_props; smil_property_t smil_props;
skipping to change at line 1948 skipping to change at line 2455
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
palign; palign;
printf("switch NEW SEQ\n"); printf("switch NEW SEQ\n");
offset -= 2; offset -= 2;
#endif #endif
smil_get_properties(&smil_props, nswitch->props); smil_get_properties(&smil_props, nswitch->props);
smil_seq(smil, snode, nswitch->child, &smil_props); smil_seq(smil, snode, nswitch->child);
smil_repeat(smil_props.repeat, node, snode, &smil_props); smil_repeat (smil_props.repeat, node, snode);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if(!strcasecmp(nswitch->name, "PAR")) { else if(!strcasecmp(nswitch->name, "PAR")) {
smil_property_t smil_props; smil_property_t smil_props;
smil_node_t *node = (*snode); smil_node_t *node = (*snode);
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset += 2; offset += 2;
palign; palign;
printf("switch NEW PAR\n"); printf("switch NEW PAR\n");
offset -= 2; offset -= 2;
#endif #endif
smil_get_properties(&smil_props, nswitch->props); smil_get_properties(&smil_props, nswitch->props);
smil_par(smil, snode, nswitch->child, &smil_props); smil_par (smil, snode, nswitch->child);
smil_repeat(smil_props.repeat, node, snode, &smil_props); smil_repeat (smil_props.repeat, node, snode);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if((!strcasecmp(nswitch->name, "VIDEO")) || else if((!strcasecmp(nswitch->name, "VIDEO")) ||
(!strcasecmp(nswitch->name, "AUDIO")) || (!strcasecmp(nswitch->name, "AUDIO")) ||
(!strcasecmp(nswitch->name, "A"))) { (!strcasecmp(nswitch->name, "A"))) {
smil_property_t smil_props; smil_property_t smil_props;
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
if(nswitch->child) { if(nswitch->child) {
skipping to change at line 2003 skipping to change at line 2510
smil_properties(smil, snode, nswitch->props, &smil_props); smil_properties(smil, snode, nswitch->props, &smil_props);
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
} }
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
offset -= 2; offset -= 2;
#endif #endif
} }
static void smil_add_mmk(int *num, mediamark_t ***mmk, smil_node_t *node) { static int smil_fill_mmk (_lf_t *lf, smil_t *smil) {
if(node->mmk) { smil_node_t *node;
(*mmk) = (mediamark_t **) realloc((*mmk), sizeof(mediamark_t *) * (*num + 2)
);
(*mmk)[*num] = node->mmk;
*num += 1;
}
if(node->next)
smil_add_mmk(num, mmk, node->next);
}
static int smil_fill_mmk(smil_t *smil, mediamark_t ***mmk) {
int num = 0; int num = 0;
if(smil->first) for (node = smil->first; node; node = node->next) {
smil_add_mmk(&num, mmk, smil->first); if (node->mmk) {
_lf_add2 (lf, node->mmk);
node->mmk = NULL;
num += 1;
}
}
return num; return num;
} }
static void smil_free_node(smil_node_t *node) {
if(node->next)
smil_free_node(node->next);
/* mmk shouldn't be fried */
smil_free_properties(&(node->prop));
free(node);
}
static void smil_free_smil(smil_t *smil) { static void smil_free_smil(smil_t *smil) {
if(smil->first) smil_node_t *node, *next;
smil_free_node(smil->first);
for (node = smil->first; node; node = next) {
next = node->next;
smil_free_properties (&node->prop);
free (node);
}
SAFE_FREE(smil->title); SAFE_FREE(smil->title);
SAFE_FREE(smil->author); SAFE_FREE(smil->author);
SAFE_FREE(smil->copyright); SAFE_FREE(smil->copyright);
SAFE_FREE(smil->year); SAFE_FREE(smil->year);
SAFE_FREE(smil->base); SAFE_FREE(smil->base);
} }
static mediamark_t **xml_smil_playlist (_lf_t *lf, xml_node_t *xml_tree) { static void xml_smil_playlist (_lf_t *lf, xml_node_t *xml_tree) {
mediamark_t **mmk = NULL;
if(xml_tree) { if(xml_tree) {
xml_node_t *smil_entry, *smil_ref; xml_node_t *smil_entry, *smil_ref;
smil_t smil; smil_t smil;
int entries_smil = 0; int entries_smil = 0;
memset(&smil, 0, sizeof(smil_t)); memset(&smil, 0, sizeof(smil_t));
if(!strcasecmp(xml_tree->name, "SMIL")) { if(!strcasecmp(xml_tree->name, "SMIL")) {
smil.first = smil.node = smil_new_node(); smil.first = smil.node = smil_new_node();
skipping to change at line 2101 skipping to change at line 2598
smil_property_t smil_props; smil_property_t smil_props;
smil_node_t *node = smil.node; smil_node_t *node = smil.node;
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
palign; palign;
printf("SEQ Found\n"); printf("SEQ Found\n");
#endif #endif
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
smil_get_properties(&smil_props, smil_ref->props); smil_get_properties(&smil_props, smil_ref->props);
smil_seq(&smil, &(smil.node), smil_ref->child, &smil_props); smil_seq(&smil, &(smil.node), smil_ref->child);
smil_repeat(smil_props.repeat, node, &(smil.node), &smil_props); smil_repeat (smil_props.repeat, node, &(smil.node));
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if(!strcasecmp(smil_ref->name, "PAR")) { else if(!strcasecmp(smil_ref->name, "PAR")) {
smil_property_t smil_props; smil_property_t smil_props;
smil_node_t *node = smil.node; smil_node_t *node = smil.node;
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
palign; palign;
printf("PAR Found\n"); printf("PAR Found\n");
#endif #endif
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
smil_get_properties(&smil_props, smil_ref->props); smil_get_properties(&smil_props, smil_ref->props);
smil_par(&smil, &(smil.node), smil_ref->child, &smil_props); smil_par (&smil, &(smil.node), smil_ref->child);
smil_repeat(smil_props.repeat, node, &(smil.node), &smil_props); smil_repeat (smil_props.repeat, node, &(smil.node));
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else if(!strcasecmp(smil_ref->name, "A")) { else if(!strcasecmp(smil_ref->name, "A")) {
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
palign; palign;
printf(" IN A\n"); printf(" IN A\n");
#endif #endif
smil_properties(&smil, &(smil.node), smil_ref->props, NULL); smil_properties(&smil, &(smil.node), smil_ref->props, NULL);
} }
else if(!strcasecmp(smil_ref->name, "SWITCH")) { else if(!strcasecmp(smil_ref->name, "SWITCH")) {
skipping to change at line 2140 skipping to change at line 2637
smil_node_t *node = smil.node; smil_node_t *node = smil.node;
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
palign; palign;
printf("SWITCH Found\n"); printf("SWITCH Found\n");
#endif #endif
smil_init_smil_property(&smil_props); smil_init_smil_property(&smil_props);
smil_get_properties(&smil_props, smil_ref->props); smil_get_properties(&smil_props, smil_ref->props);
smil_switch(&smil, &(smil.node), smil_ref->child, &smil_props); smil_switch (&smil, &(smil.node), smil_ref->child);
smil_repeat(smil_props.repeat, node, &(smil.node), &smil_props); smil_repeat (smil_props.repeat, node, &(smil.node));
smil_free_properties(&smil_props); smil_free_properties(&smil_props);
} }
else { else {
smil_properties(&smil, &smil.node, smil_ref->props, NULL); smil_properties(&smil, &smil.node, smil_ref->props, NULL);
} }
smil_ref = smil_ref->next; smil_ref = smil_ref->next;
} }
} }
else if(!strcasecmp(smil_entry->name, "SEQ")) { /* smil2, kino format(no body) */ else if(!strcasecmp(smil_entry->name, "SEQ")) { /* smil2, kino format(no body) */
skipping to change at line 2168 skipping to change at line 2665
#ifdef DEBUG_SMIL #ifdef DEBUG_SMIL
printf("DUMPING TREE:\n"); printf("DUMPING TREE:\n");
printf("-------------\n"); printf("-------------\n");
smil_dump_tree(smil.first); smil_dump_tree(smil.first);
printf("DUMPING HEADER:\n"); printf("DUMPING HEADER:\n");
printf("---------------\n"); printf("---------------\n");
smil_dump_header(&smil); smil_dump_header(&smil);
#endif #endif
entries_smil = smil_fill_mmk(&smil, &mmk); entries_smil = smil_fill_mmk (lf, &smil);
smil_free_smil(&smil); smil_free_smil(&smil);
} }
#ifdef DEBUG #ifdef DEBUG
else else
fprintf(stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, xml_tree->name); fprintf(stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, xml_tree->name);
#endif #endif
if (entries_smil) { if (entries_smil) {
mmk[entries_smil] = NULL;
lf->num_entries = entries_smil; lf->num_entries = entries_smil;
lf->type = "SMIL"; lf->type = "SMIL";
return mmk;
} }
} }
return NULL;
} }
/* /*
* ********************************** SMIL END ********************************* ** * ********************************** SMIL END ********************************* **
*/ */
static mediamark_t **xml_freevo_playlist (_lf_t *lf, xml_node_t *xml_tree) { static void xml_freevo_playlist (_lf_t *lf, xml_node_t *xml_tree) {
mediamark_t **mmk = NULL; int entries_fvo = 0;
if(xml_tree) { if (!strcasecmp (xml_tree->name, "FREEVO")) {
xml_node_t *fvo_entry; mediamark_t m = { .end = -1, .from = MMK_FROM_PLAYLIST };
xml_property_t *fvo_prop; xml_node_t *fvo_entry;
int entries_fvo = 0;
for (fvo_entry = xml_tree->child; fvo_entry; fvo_entry = fvo_entry->next) {
if(!strcasecmp(xml_tree->name, "FREEVO")) { if (!strcasecmp (fvo_entry->name, "MOVIE")) {
char *origin; char *url = NULL, *sub = NULL, *title = NULL;
char *url = NULL; xml_node_t *sentry;
char *sub = NULL; xml_property_t *fvo_prop;
char *title = NULL;
for (fvo_prop = fvo_entry->props; fvo_prop; fvo_prop = fvo_prop->next) {
origin = get_basedir (lf->filename); if (!strcasecmp (fvo_prop->name, "TITLE"))
title = fvo_prop->value;
fvo_entry = xml_tree->child; }
for (sentry = fvo_entry->child; sentry; sentry = sentry->next) {
while(fvo_entry) { if ((!strcasecmp (sentry->name, "VIDEO")) || (!strcasecmp (sentry->nam
if(!strcasecmp(fvo_entry->name, "MOVIE")) { e, "AUDIO"))) {
xml_node_t *sentry; xml_node_t *ssentry;
for(fvo_prop = fvo_entry->props; fvo_prop; fvo_prop = fvo_prop->next) { for (ssentry = sentry->child; ssentry; ssentry = ssentry->next) {
if(!strcasecmp(fvo_prop->name, "TITLE")) { if (!strcasecmp (ssentry->name, "SUBTITLE")) {
title = fvo_prop->value; sub = ssentry->data;
} } else if (!strcasecmp (ssentry->name, "URL") || !strcasecmp (ssen
} try->name, "DVD") ||
!strcasecmp (ssentry->name, "VCD") || !strcasecmp (ssentry->name
sentry = fvo_entry->child; , "FILE")) {
while(sentry) { url = ssentry->data;
}
if((!strcasecmp(sentry->name, "VIDEO")) || (!strcasecmp(sentry->name, }
"AUDIO"))) { if (url) {
xml_node_t *ssentry = sentry->child; m.mrl = url;
m.ident = title;
while(ssentry) { m.sub = sub;
_lf_add (lf, entries_fvo, &m);
if(!strcasecmp(ssentry->name, "SUBTITLE")) { lf->num_entries = ++entries_fvo;
sub = ssentry->data; url = NULL;
} }
else if((!strcasecmp(ssentry->name, "URL")) || sub = NULL;
(!strcasecmp(ssentry->name, "DVD")) || (!strcasecmp(ssent }
ry->name, "VCD"))) { }
url = strdup(ssentry->data); title = NULL;
}
else if(!strcasecmp(ssentry->name, "FILE")) {
if(origin) {
size_t l1 = strlen (origin), l2 = strlen (ssentry->data);
url = (char *)malloc (l1 + l2 + 2);
if (l1) {
memcpy (url, origin, l1);
if ((url[l1 - 1] == '/') && (ssentry->data[0] == '/'))
l1 -= 1;
}
memcpy (url + l1, ssentry->data, l2 + 1);
}
else
url = strdup(ssentry->data);
}
if(url) {
mmk = (mediamark_t **) realloc(mmk, sizeof(mediamark_t *) * (en
tries_fvo + 2));
mediamark_store_mmk(&mmk[entries_fvo], url, title, sub, 0, -1,
0, 0);
lf->num_entries = ++entries_fvo;
free(url);
url = NULL;
}
sub = NULL;
ssentry = ssentry->next;
}
}
sentry = sentry->next;
}
}
title = NULL;
fvo_entry = fvo_entry->next;
} }
free(origin);
} }
}
#ifdef DEBUG #ifdef DEBUG
else else
fprintf(stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, fprintf (stderr, "%s(): Unsupported XML type: '%s'.\n", __XINE_FUNCTION__, x
xml_tree->name); ml_tree->name);
#endif #endif
if (entries_fvo)
if(entries_fvo) { lf->type = "FREEVO";
mmk[entries_fvo] = NULL;
lf->type = "FREEVO";
return mmk;
}
}
return NULL;
} }
static mediamark_t **guess_xml_based_playlist (_lf_t *lf) { static void guess_xml_based_playlist (_lf_t *lf) {
mediamark_t **mmk = NULL;
char *xml_content; char *xml_content;
int result;
xml_node_t *xml_tree, *top_xml_tree;
if ((xml_content = _lf_dup (lf)) != NULL) { if ((xml_content = _lf_dup (lf)) != NULL) {
int i; static const playlist_xml_guess_func_t guess_functions[] = {
playlist_xml_guess_func_t guess_functions[] = {
xml_asx_playlist, xml_asx_playlist,
xml_gx_playlist, xml_gx_playlist,
xml_noatun_playlist, xml_noatun_playlist,
xml_smil_playlist, xml_smil_playlist,
xml_freevo_playlist, xml_freevo_playlist,
NULL NULL
}; };
xml_node_t *xml_tree = NULL;
xml_parser_init_R (xml_parser_t *xml, xml_content, lf->size, XML_PARSER_CASE _INSENSITIVE); xml_parser_init_R (xml_parser_t *xml, xml_content, lf->size, XML_PARSER_CASE _INSENSITIVE);
if ((result = xml_parser_build_tree_R (xml, &xml_tree)) != XML_PARSER_OK) if ((xml_parser_build_tree_R (xml, &xml_tree) == XML_PARSER_OK) && xml_tree)
goto __failure; {
int i;
top_xml_tree = xml_tree; /* Check all playlists */
for (i = 0; guess_functions[i]; i++) {
/* Check all playlists */ guess_functions[i] (lf, xml_tree);
for (i = 0; guess_functions[i]; i++) { if (lf->type[0])
if ((mmk = guess_functions[i] (lf, xml_tree))) break;
break; }
xml_parser_free_tree (xml_tree);
} }
xml_parser_free_tree (top_xml_tree);
__failure:
xml_parser_finalize_R (xml); xml_parser_finalize_R (xml);
} }
return mmk;
} }
/* /*
* XML based playlists end. * XML based playlists end.
*/ */
/* /*
* Public * Public
*/ */
int mediamark_get_entry_from_id (gGui_t *gui, const char *ident) { int mediamark_get_entry_from_id (gGui_t *gui, const char *ident) {
if(ident && gui->playlist.num) { if(ident && gui->playlist.num) {
int i; int i;
for(i = 0; i < gui->playlist.num; i++) { for(i = 0; i < gui->playlist.num; i++) {
if(!strcasecmp(ident, gui->playlist.mmk[i]->ident)) if(!strcasecmp(ident, gui->playlist.mmk[i]->ident))
return i; return i;
} }
} }
return -1; return -1;
} }
void mediamark_insert_entry (gGui_t *gui, int index, const char *mrl, const char static int _gui_playlist_insert (gGui_t *gui, int index, const char *mrl, const
*ident, char *ident,
const char *sub, int start, int end, int av_offset, i const char *sub, int start, int end, int av_offset, int spu_offset) {
nt spu_offset) {
char autosub[2*XITK_PATH_MAX + XITK_NAME_MAX + 2]; char autosub[2*XITK_PATH_MAX + XITK_NAME_MAX + 2];
char subpath[XITK_PATH_MAX + XITK_NAME_MAX + 2]; char subpath[XITK_PATH_MAX + XITK_NAME_MAX + 2];
DIR *dir; DIR *dir;
struct dirent *dentry; struct dirent *dentry;
gui->playlist.mmk = (mediamark_t **) realloc(gui->playlist.mmk, sizeof(mediama if (!mrl[0])
rk_t *) * (gui->playlist.num + 2)); return -1;
gui_playlist_lock (gui);
if(index < gui->playlist.num) if ((index < 0) || (index >= gui->playlist.num))
memmove(&gui->playlist.mmk[index+1], &gui->playlist.mmk[index], index = gui->playlist.num;
(gui->playlist.num - index) * sizeof(gui->playlist.mmk[0]) );
if (gui->playlist.num + 1 > gui->playlist.max) {
int i;
mediamark_t **mmk = realloc (gui->playlist.mmk, sizeof (*mmk) * (gui->playli
st.num + 32));
if (!mmk) {
gui_playlist_unlock (gui);
return -1;
}
gui->playlist.mmk = mmk;
gui->playlist.max += 32;
for (i = gui->playlist.num; i < gui->playlist.max; i++)
mmk[i] = NULL;
}
{
int i;
for (i = gui->playlist.num; i > index; i--)
gui->playlist.mmk[i] = gui->playlist.mmk[i - 1];
}
gui->playlist.mmk[index] = NULL;
gui->playlist.num++;
/* /*
* If subtitle_autoload is enabled and subtitle is NULL * If subtitle_autoload is enabled and subtitle is NULL
* then try to see if a matching subtitle exist * then try to see if a matching subtitle exist
*/ */
if(mrl && (!sub) && gui->subtitle_autoload) { if(mrl && (!sub) && gui->subtitle_autoload) {
if(mrl_look_like_file((char *) mrl)) { if (mrl_look_like_file (mrl)) {
char *know_subs = "sub,srt,asc,smi,ssa,ass,txt"; char *know_subs = "sub,srt,asc,smi,ssa,ass,txt";
char *vsubs, *pvsubs; char *vsubs, *pvsubs;
char *_mrl, *ending, *ext, *path, *d_name; char *_mrl, *ending, *ext, *path, *d_name;
struct stat pstat; struct stat pstat;
_mrl = (char *) mrl; _mrl = (char *) mrl;
if(!strncasecmp(_mrl, "file:", 5)) if(!strncasecmp(_mrl, "file:", 5))
_mrl += 5; _mrl += 5;
strlcpy(autosub, _mrl, sizeof(autosub)); strlcpy(autosub, _mrl, sizeof(autosub));
if((ending = strrchr(autosub, '.'))) if((ending = strrchr(autosub, '.')))
ending++; ending++;
else { else {
ending = autosub + strlen(autosub); ending = autosub + xitk_find_byte (autosub, 0);
*ending++ = '.'; *ending++ = '.';
} }
vsubs = strdup(know_subs); vsubs = strdup(know_subs);
pvsubs = vsubs; pvsubs = vsubs;
while((ext = xine_strsep(&pvsubs, ",")) && !sub) { while((ext = xine_strsep(&pvsubs, ",")) && !sub) {
strcpy(ending, ext); strcpy(ending, ext);
*(ending + strlen(ext) + 1) = '\0'; *(ending + xitk_find_byte (ext, 0) + 1) = '\0';
if(((stat(autosub, &pstat)) > -1) && (S_ISREG(pstat.st_mode)) && strcmp(a utosub, _mrl)) if(((stat(autosub, &pstat)) > -1) && (S_ISREG(pstat.st_mode)) && strcmp(a utosub, _mrl))
sub = autosub; sub = autosub;
} }
free(vsubs); free(vsubs);
/* try matching "<name>.*.<know_subs>" like used by opensubtitles */ /* try matching "<name>.*.<know_subs>" like used by opensubtitles */
if( !sub ) { if( !sub ) {
*ending = '\0'; *ending = '\0';
skipping to change at line 2413 skipping to change at line 2871
if((d_name = strrchr(subpath, '/'))) { if((d_name = strrchr(subpath, '/'))) {
*d_name++ = '\0'; *d_name++ = '\0';
path = subpath; path = subpath;
} else { } else {
d_name = subpath; d_name = subpath;
path = "."; path = ".";
} }
if((dir = opendir(path))) { if((dir = opendir(path))) {
while((dentry = readdir(dir))) { while((dentry = readdir(dir))) {
if( (strncmp(dentry->d_name, d_name, strlen(d_name)) == 0) && if( (strncmp(dentry->d_name, d_name, xitk_find_byte (d_name, 0)) == 0) &&
(ending = strrchr(dentry->d_name, '.')) ) { (ending = strrchr(dentry->d_name, '.')) ) {
if( strstr(know_subs, ending+1) ) { if( strstr(know_subs, ending+1) ) {
snprintf(autosub,sizeof(autosub),"%s/%s",path,dentry->d_name); snprintf(autosub,sizeof(autosub),"%s/%s",path,dentry->d_name);
autosub[sizeof(autosub)-1]='\0'; autosub[sizeof(autosub)-1]='\0';
if(((stat(autosub, &pstat)) > -1) && (S_ISREG(pstat.st_mode)) && strcmp(autosub, _mrl)) { if(((stat(autosub, &pstat)) > -1) && (S_ISREG(pstat.st_mode)) && strcmp(autosub, _mrl)) {
sub = autosub; sub = autosub;
break; break;
} }
} }
} }
} }
closedir(dir); closedir(dir);
} }
} }
} }
}
{
mediamark_t m = {
.mrl = (char *)mrl, /** << will not be written to. */
.ident = (char *)ident,
.sub = (char *)sub,
.start = start,
.end = end,
.type = MMK_TYPE_FILE,
.from = MMK_FROM_USER,
.av_offset = av_offset,
.spu_offset = spu_offset
};
mediamark_copy (&gui->playlist.mmk[index], &m);
} }
if(mediamark_store_mmk(&gui->playlist.mmk[index], gui_playlist_unlock (gui);
mrl, ident, sub, start, end, av_offset, spu_offset)) return index;
gui->playlist.num++;
} }
void mediamark_append_entry (gGui_t *gui, const char *mrl, const char *ident, int gui_playlist_insert (gGui_t *gui, int index, const char *mrl, const char *id ent,
const char *sub, int start, int end, int av_offset, int spu_offset) { const char *sub, int start, int end, int av_offset, int spu_offset) {
mediamark_insert_entry (gui, gui->playlist.num, mrl, ident, sub, start, end, a int ret;
v_offset, spu_offset);
if (!mrl)
return -1;
gui_playlist_lock (gui);
ret = _gui_playlist_insert (gui, index, mrl, ident, sub, start, end, av_offset
, spu_offset);
gui_playlist_unlock (gui);
return ret;
} }
void mediamark_free_mediamarks (gGui_t *gui) { int gui_playlist_move (gGui_t *gui, int index, int n, int diff) {
int res;
gui_playlist_lock (gui);
do {
mediamark_t *stemp[32], **temp = stemp;
res = GUI_MMK_NONE;
if (gui->playlist.num <= 0)
break;
if (index == GUI_MMK_CURRENT)
index = gui->playlist.cur;
if ((index < 0) || (index >= gui->playlist.num))
break;
res = index;
if (n > gui->playlist.num - index)
n = gui->playlist.num - index;
if (diff == 0)
break;
if (diff < 0) {
diff = -diff;
if (diff > index) {
diff = index;
if (diff <= 0)
break;
}
if (diff > 32) {
temp = malloc (diff * sizeof (*temp));
if (!temp)
break;
}
if (gui->playlist.cur < index) {
if (gui->playlist.cur >= index - diff)
gui->playlist.cur += n;
} else {
if (gui->playlist.cur < index + n)
gui->playlist.cur -= diff;
}
memcpy (temp, gui->playlist.mmk + index - diff, diff * sizeof (*temp));
memmove (gui->playlist.mmk + index - diff, gui->playlist.mmk + index, n *
sizeof (*temp));
memcpy (gui->playlist.mmk + index - diff + n, temp, diff * sizeof (*temp))
;
res = index - diff;
} else /* diff > 0 */ {
if (diff > gui->playlist.num - index - n) {
diff = gui->playlist.num - index - n;
if (diff <= 0)
break;
}
if (diff > 32) {
temp = malloc (diff * sizeof (*temp));
if (!temp)
break;
}
if (gui->playlist.cur < index + n) {
if (gui->playlist.cur >= index)
gui->playlist.cur += diff;
} else {
if (gui->playlist.cur < index + n + diff)
gui->playlist.cur -= n;
}
memcpy (temp, gui->playlist.mmk + index + n, diff * sizeof (*temp));
memmove (gui->playlist.mmk + index + diff, gui->playlist.mmk + index, n *
sizeof (*temp));
memcpy (gui->playlist.mmk + index, temp, diff * sizeof (*temp));
res = index + diff;
}
if (temp != stemp)
free (temp);
} while (0);
gui_playlist_unlock (gui);
return res;
}
void gui_playlist_free (gGui_t *gui) {
gui_playlist_lock (gui);
if(gui->playlist.num > 0) { if(gui->playlist.num > 0) {
int i; int i;
for (i = 0; i < gui->playlist.num; i++) for (i = 0; i < gui->playlist.num; i++)
mediamark_free_mmk(&gui->playlist.mmk[i]); mediamark_free(&gui->playlist.mmk[i]);
SAFE_FREE(gui->playlist.mmk); SAFE_FREE(gui->playlist.mmk);
gui->playlist.max = 0;
gui->playlist.num = 0; gui->playlist.num = 0;
gui->playlist.cur = -1; gui->playlist.cur = -1;
} }
gui_playlist_unlock (gui);
} }
void mediamark_reset_played_state (gGui_t *gui) { void mediamark_reset_played_state (gGui_t *gui) {
if(gui->playlist.num) { if(gui->playlist.num) {
int i; int i;
for(i = 0; i < gui->playlist.num; i++) for(i = 0; i < gui->playlist.num; i++)
gui->playlist.mmk[i]->played = 0; gui->playlist.mmk[i]->played = 0;
} }
} }
skipping to change at line 2521 skipping to change at line 3077
if(found == 2) if(found == 2)
next = gui->playlist.cur; next = gui->playlist.cur;
} }
else if(gui->playlist.num == 2) else if(gui->playlist.num == 2)
next = !gui->playlist.cur; next = !gui->playlist.cur;
return next; return next;
} }
void mediamark_replace_entry(mediamark_t **mmk, int gui_playlist_remove (gGui_t *gui, int index) {
const char *mrl, const char *ident, const char *sub, int i;
int start, int end, int av_offset, int spu_offset) { gui_playlist_lock (gui);
SAFE_FREE((*mmk)->mrl);
SAFE_FREE((*mmk)->ident); if (index == GUI_MMK_CURRENT)
SAFE_FREE((*mmk)->sub); index = gui->playlist.cur;
mediamark_free_alternates((*mmk)); if ((index < gui->playlist.num) && (index >= 0) && gui->playlist.mmk) {
(*mmk)->start = 0; mediamark_free (&gui->playlist.mmk[index]);
(*mmk)->end = -1; for (i = index; i < gui->playlist.num - 1; i++)
(*mmk)->av_offset = 0;
(*mmk)->spu_offset = 0;
(void) mediamark_store_mmk(mmk, mrl, ident, sub, start, end, av_offset, spu_of
fset);
}
mediamark_t *mediamark_get_current_mmk (gGui_t *gui) {
if(gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
gui->playlist.mmk[gui->playlist.cur])
return gui->playlist.mmk[gui->playlist.cur];
return (mediamark_t *) NULL;
}
mediamark_t *mediamark_get_mmk_by_index (gGui_t *gui, int index) {
if(index < gui->playlist.num && index >= 0 && gui->playlist.mmk &&
gui->playlist.mmk[index])
return gui->playlist.mmk[index];
return (mediamark_t *) NULL;
}
const char *mediamark_get_current_mrl (gGui_t *gui) {
if(gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
gui->playlist.mmk[gui->playlist.cur] &&
gui->playlist.cur < gui->playlist.num)
return gui->playlist.mmk[gui->playlist.cur]->mrl;
return NULL;
}
const char *mediamark_get_current_ident (gGui_t *gui) {
if(gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
gui->playlist.mmk[gui->playlist.cur])
return gui->playlist.mmk[gui->playlist.cur]->ident;
return NULL;
}
const char *mediamark_get_current_sub (gGui_t *gui) {
if(gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
gui->playlist.mmk[gui->playlist.cur])
return gui->playlist.mmk[gui->playlist.cur]->sub;
return NULL;
}
void mediamark_delete_entry (gGui_t *gui, int offset) {
if(offset < gui->playlist.num && offset >= 0 && gui->playlist.mmk &&
gui->playlist.mmk[offset]) {
int i;
mediamark_free_mmk(&gui->playlist.mmk[offset]);
for (i = offset; i < gui->playlist.num; i++)
gui->playlist.mmk[i] = gui->playlist.mmk[i + 1]; gui->playlist.mmk[i] = gui->playlist.mmk[i + 1];
gui->playlist.num--; gui->playlist.num--;
gui->playlist.mmk[gui->playlist.num] = NULL; gui->playlist.mmk[gui->playlist.num] = NULL;
if (gui->playlist.cur >= gui->playlist.num)
gui->playlist.mmk = (mediamark_t **) realloc(gui->playlist.mmk, sizeof(media gui->playlist.cur = -1;
mark_t *) * (gui->playlist.num + 2));
} }
}
static _lf_t *_lf_get (gGui_t *gui, const char *_filename) {
_lf_t *lf;
const char *filename = _filename;
if(_filename) { i = gui->playlist.num;
if(!strncasecmp("file:/", _filename, 6)) gui_playlist_unlock (gui);
filename = (_filename + 6); return i;
}
static void _gui_playlist_add_lf (gGui_t *gui, _lf_t *lf) {
if (gui->playlist.num + (int)lf->used > gui->playlist.max) {
int nmax = (gui->playlist.num + lf->used + 32) & ~31;
mediamark_t **nmmk = realloc (gui->playlist.mmk, nmax * sizeof (*nmmk));
if (nmmk) {
gui->playlist.mmk = nmmk;
gui->playlist.max = nmax;
}
}
{
uint32_t n = gui->playlist.max - gui->playlist.num, i, t;
if (n > lf->used)
n = lf->used;
for (t = gui->playlist.num, i = 0; i < n; i++) {
if (!lf->mmk[i])
continue;
lf->mmk[i]->from = MMK_FROM_PLAYLIST;
if (!lf->mmk[i]->ident) {
char *start = lf->mmk[i]->mrl;
if (start[0] == '/') {
char *lastpart;
for (lastpart = start + xitk_find_byte (start, 0); lastpart[-1] != '/'
; lastpart--) ;
lf->mmk[i]->ident = strdup (lastpart);
}
}
if (!lf->mmk[i]->ident)
lf->mmk[i]->ident = lf->mmk[i]->mrl;
gui->playlist.mmk[t++] = lf->mmk[i];
}
gui->playlist.num = t;
for (; i < lf->used; i++)
mediamark_free (&lf->mmk[i]);
} }
lf = _read_file (gui, filename);
if (!lf)
return NULL;
_lf_ext (lf, filename);
return lf;
} }
int mediamark_concat_mediamarks (gGui_t *gui, const char *filename) { static int _gui_playlist_add_playlist (gGui_t *gui, mrl_buf_t *name, int replace ) {
_lf_t *lf; _lf_t *lf;
size_t i; size_t i;
mediamark_t **mmk = NULL;
static const playlist_guess_func_t guess_functions[] = { static const playlist_guess_func_t guess_functions[] = {
guess_xml_based_playlist, guess_xml_based_playlist,
guess_toxine_playlist, guess_toxine_playlist,
guess_pls_playlist, guess_pls_playlist,
guess_m3u_playlist, guess_m3u_playlist,
guess_sfv_playlist, guess_sfv_playlist,
guess_raw_playlist, guess_raw_playlist,
NULL NULL
}; };
lf = _lf_get (gui, filename); lf = _lf_get (gui, name);
if (!lf) if (!lf)
return 0; return 0;
for (i = 0; guess_functions[i]; i++) { for (i = 0; guess_functions[i]; i++) {
if ((mmk = guess_functions[i] (lf))) guess_functions[i] (lf);
if (lf->type[0])
break; break;
} }
if(mmk) { if (lf->mmk) {
#ifdef DEBUG #ifdef DEBUG
printf("Playlist file (%s) is valid (%s).\n", filename, lf->type); printf("Playlist file (%s) is valid (%s).\n", name->start, lf->type);
#endif #endif
} }
else { else {
fprintf(stderr, _("Playlist file (%s) is invalid.\n"), filename); fprintf (stderr, _("Playlist file (%s) is invalid.\n"), name->start);
_lf_delete (lf); _lf_delete (lf);
return 0; return 0;
} }
gui->playlist.cur = gui->playlist.num; {
int n;
for (i = 0; i < lf->num_entries; i++) gui_playlist_lock (gui);
mediamark_append_entry (gui, mmk[i]->mrl, mmk[i]->ident, mmk[i]->sub, if (replace) {
mmk[i]->start, mmk[i]->end, mmk[i]->av_offset, mmk[i]- for (n = 0; n < gui->playlist.num; n++)
>spu_offset); mediamark_free (gui->playlist.mmk + i);
gui->playlist.num = 0;
for (i = 0; i < lf->num_entries; i++) }
(void) mediamark_free_mmk(&mmk[i]); n = gui->playlist.num;
_gui_playlist_add_lf (gui, lf);
SAFE_FREE (mmk); if (replace)
_lf_delete (lf); gui->playlist.cur = (gui->playlist.loop == PLAYLIST_LOOP_SHUFFLE) ? mediam
return 1; ark_get_shuffle_next (gui) : 0;
else if ((gui->playlist.cur < 0) && (gui->playlist.num > n))
gui->playlist.cur = n;
n = gui->playlist.num - n;
gui_playlist_unlock (gui);
_lf_delete (lf);
return n;
}
} }
void mediamark_load_mediamarks (gGui_t *gui, const char *filename) { static char *_int2str (char *buf, int value) {
_lf_t *lf; unsigned int minus, u;
int i, onum;
mediamark_t **mmk = NULL, **ommk;
static const playlist_guess_func_t guess_functions[] = {
guess_xml_based_playlist,
guess_toxine_playlist,
guess_pls_playlist,
guess_m3u_playlist,
guess_sfv_playlist,
guess_raw_playlist,
NULL
};
lf = _lf_get (gui, filename); if (value >= 0)
if (!lf) minus = 0, u = value;
else
minus = 1, u = -value;
do {
*--buf = (u % 10u) + '0';
u /= 10u;
} while (u);
if (minus)
*--buf = '-';
return buf;
}
void gui_playlist_save (gGui_t *gui, const char *filename) {
mrl_buf_t base, item, full;
FILE *fd;
int i;
gui_playlist_lock (gui);
i = gui->playlist.num;
gui_playlist_unlock (gui);
if (i <= 0)
return; return;
for (i = 0; guess_functions[i]; i++) { mrl_buf_init (&base);
if ((mmk = guess_functions[i] (lf))) mrl_buf_init (&item);
break; mrl_buf_init (&full);
} _mrl_buf_working_dir (&base);
mrl_buf_set (&item, &base, filename);
mrl_buf_merge (&full, &base, &item);
if (!_mrl_buf_mkdir_p (&full))
return;
if(mmk) { fd = fopen (full.root, "wb");
#ifdef DEBUG if (!fd) {
printf("Playlist file (%s) is valid (%s).\n", filename, lf->type); fprintf (stderr, _("Unable to save playlist (%s): %s.\n"), filename, strerro
#endif r (errno));
}
else {
fprintf(stderr, _("Playlist file (%s) is invalid.\n"), filename);
_lf_delete (lf);
return; return;
} }
ommk = gui->playlist.mmk; fwrite ("# toxine playlist\n", 1, 18, fd);
onum = gui->playlist.num;
gui->playlist.mmk = mmk; gui_playlist_lock (gui);
gui->playlist.num = lf->num_entries; for (i = 0; i < gui->playlist.num; i++) {
char buf[4 * 32], *p;
fwrite ("\nentry {\n\tidentifier = ", 1, 23, fd);
fwrite (gui->playlist.mmk[i]->ident, 1, xitk_find_byte (gui->playlist.mmk[i]
->ident, 0), fd);
mrl_buf_set (&item, &base, gui->playlist.mmk[i]->mrl);
mrl_buf_merge (&full, &base, &item);
fwrite (";\n\tmrl = ", 1, 9, fd);
fwrite (full.start, 1, full.end - full.start, fd);
if (gui->playlist.mmk[i]->sub) {
mrl_buf_set (&item, &base, gui->playlist.mmk[i]->sub);
mrl_buf_merge (&full, &base, &item);
fwrite (";\n\tsubtitle = ", 1, 14, fd);
fwrite (full.start, 1, full.end - full.start, fd);
}
p = buf + sizeof (buf);
p -= 3; memcpy (p, "};\n", 3);
if (gui->playlist.mmk[i]->spu_offset != 0) {
p -= 2; memcpy (p, ";\n", 2);
p = _int2str (p, gui->playlist.mmk[i]->spu_offset);
p -= 14; memcpy (p, "\tspu_offset = ", 14);
}
if (gui->playlist.mmk[i]->av_offset != 0) {
p -= 2; memcpy (p, ";\n", 2);
p = _int2str (p, gui->playlist.mmk[i]->av_offset);
p -= 13; memcpy (p, "\tav_offset = ", 13);
}
if (gui->playlist.mmk[i]->end != -1) {
p -= 2; memcpy (p, ";\n", 2);
p = _int2str (p, gui->playlist.mmk[i]->end);
p -= 7; memcpy (p, "\tend = ", 7);
}
if (gui->playlist.mmk[i]->start > 0) {
p -= 2; memcpy (p, ";\n", 2);
p = _int2str (p, gui->playlist.mmk[i]->start);
p -= 9; memcpy (p, "\tstart = ", 9);
}
p -= 2; memcpy (p, ";\n", 2);
fwrite (p, 1, buf + sizeof (buf) - p, fd);
}
gui_playlist_unlock (gui);
if(gui->playlist.loop == PLAYLIST_LOOP_SHUFFLE) fwrite ("# END\n", 1, 6, fd);
gui->playlist.cur = mediamark_get_shuffle_next (gui);
else
gui->playlist.cur = 0;
for(i = 0; i < onum; i++) fclose (fd);
(void) mediamark_free_mmk(&ommk[i]); #ifdef DEBUG
printf ("Playlist '%s' saved.\n", filename);
#endif
}
SAFE_FREE(ommk); size_t mrl_get_lowercase_prot (char *buf, size_t bsize, const char *mrl) {
union {uint8_t s[16]; uint32_t v[4];} _buf;
uint8_t *p = (uint8_t *)mrl, *s = _buf.s, *e = s + 14;
uint32_t u;
_lf_delete (lf); if (!p)
} return 0;
void mediamark_save_mediamarks (gGui_t *gui, const char *filename) { while ((*p >= 'A') && (s < e))
char *fullfn; *s++ = *p++;
char *pn; if (p[0] != ':')
char *fn; return 0;
int status = 1; if (p[1] != '/')
return 0;
for (u = 0; u < 4; u++)
_buf.v[u] |= 0x20202020;
s[0] = 0;
u = s - _buf.s;
if(!gui->playlist.num) if (buf && (bsize > u))
return; memcpy (buf, _buf.s, u + 1);
return u;
}
fullfn = strdup(filename); int mrl_look_like_file (const char *mrl) {
char buf[16];
size_t l = mrl_get_lowercase_prot (buf, sizeof (buf), mrl);
pn = fullfn; if (l == 0)
return 1;
return (l == 4) && !memcmp (buf, "file", 4) ? 1 : 0;
}
fn = strrchr(fullfn, '/'); static int _gui_mmk_cmp (void *a, void *b) {
mediamark_t *d = (mediamark_t *)a;
mediamark_t *e = (mediamark_t *)b;
if(fn) { return strcmp (d->ident, e->ident);
*fn = '\0'; }
fn++;
status = mkdir_safe(pn);
}
else
fn = pn;
if(status && fn) { static void _gui_mmk_sort (xine_sarray_t *sarray, mediamark_t **list, uint32_t n
int i; ) {
FILE *fd; uint32_t u;
const char *store_item;
char buffer[_PATH_MAX + _NAME_MAX + 2], current_dir[_PATH_MAX + 1];
if (getcwd (current_dir, sizeof (current_dir))) {
size_t dl = strlen (current_dir);
if (dl && (current_dir[dl - 1] != '/'))
strcpy (current_dir + dl, "/");
} else
strcpy(current_dir, "");
if((fd = fopen(filename, "w")) != NULL) {
fprintf(fd, "# toxine playlist\n");
for(i = 0; i < gui->playlist.num; i++) {
fprintf(fd, "\nentry {\n");
fprintf(fd, "\tidentifier = %s;\n", gui->playlist.mmk[i]->ident);
store_item = concat_basedir(buffer, sizeof(buffer), current_dir, gui->pla
ylist.mmk[i]->mrl);
fprintf(fd, "\tmrl = %s;\n", store_item);
if(gui->playlist.mmk[i]->sub) {
store_item = concat_basedir(buffer, sizeof(buffer), current_dir, gui->p
laylist.mmk[i]->sub);
fprintf(fd, "\tsubtitle = %s;\n", store_item);
}
if(gui->playlist.mmk[i]->start > 0)
fprintf(fd, "\tstart = %d;\n", gui->playlist.mmk[i]->start);
if(gui->playlist.mmk[i]->end != -1)
fprintf(fd, "\tend = %d;\n", gui->playlist.mmk[i]->end);
if(gui->playlist.mmk[i]->av_offset != 0)
fprintf(fd, "\tav_offset = %d;\n", gui->playlist.mmk[i]->av_offset);
if(gui->playlist.mmk[i]->spu_offset != 0)
fprintf(fd, "\tspu_offset = %d;\n", gui->playlist.mmk[i]->spu_offset);
fprintf(fd,"};\n");
}
fprintf(fd, "# END\n"); if (!sarray)
return;
fclose(fd); xine_sarray_clear (sarray);
#ifdef DEBUG for (u = 0; u < n; u++)
printf("Playlist '%s' saved.\n", filename); xine_sarray_add (sarray, list[u]);
#endif for (u = 0; u < n; u++)
list[u] = xine_sarray_get (sarray, u);
}
static int _gui_playlist_dupl_cmp (void *a, void *b) {
mediamark_t *d = (mediamark_t *)a;
mediamark_t *e = (mediamark_t *)b;
return strcmp (d->mrl + d->start, e->mrl + e->start);
}
int gui_playlist_add_item (gGui_t *gui, const char *filepathname, int max_levels
, gui_item_type_t itemtype, int replace) {
mrl_buf_t base, name, *mrlb;
DIR *dirs[GUI_MAX_DIR_LEVELS];
char *add[GUI_MAX_DIR_LEVELS];
int num_subdirs[GUI_MAX_DIR_LEVELS];
xine_sarray_t *sarray, *dupl;
struct stat sbuf;
char *start, *end;
int n, level, sort_start = 0, all_files = 0, old_num;
int type;
if (max_levels < 0) {
max_levels = -max_levels;
all_files = 1;
}
if (max_levels > GUI_MAX_DIR_LEVELS)
max_levels = GUI_MAX_DIR_LEVELS;
mrl_buf_init (&name);
mrl_buf_set (&name, NULL, filepathname);
if (mrl_buf_is_file (&name)) {
if (name.root[0] != '/') {
mrl_buf_init (&base);
_mrl_buf_working_dir (&base);
mrl_buf_merge (&base, &base, &name);
start = base.root;
add[0] = base.end;
end = base.max;
mrlb = &base;
} else {
start = name.start;
add[0] = name.end;
end = name.max;
mrlb = &name;
}
type = MMK_TYPE_FILE;
start[-1] = 0;
if (add[0][-1] == '/')
(--add[0])[0] = 0;
} else {
start = name.start;
add[0] = name.end;
end = name.max;
mrlb = &name;
type = MMK_TYPE_NET;
}
/* add not found item to get the user error msg. */
n = stat (start, &sbuf);
if (n || S_ISREG (sbuf.st_mode)) {
char *lastpart, *ext, *sub;
uint32_t vext;
/* test for "/some/dir/video.flv;;/some/dir/subtitiles.txt" */
start[-2] = start[-1] = ';';
for (sub = add[0]; sub >= start + 3; sub--) {
while (sub[-1] != ';')
sub--;
if (sub[-2] == ';')
break;
}
if (sub >= start + 3) {
sub[-2] = 0;
mrlb->args = mrlb->info = mrlb->end = add[0] = sub - 2;
start[-1] = '/';
for (lastpart = add[0]; lastpart[-1] != '/'; lastpart--) ;
mrlb->lastpart = lastpart;
lastpart[-1] = '.';
for (ext = add[0]; ext[-1] != '.'; ext--) ;
lastpart[-1] = '/';
if (ext <= lastpart)
ext = add[0];
mrlb->ext = ext;
} else {
sub = NULL;
lastpart = mrlb->lastpart;
ext = mrlb->ext;
} }
else
fprintf(stderr, _("Unable to save playlist (%s): %s.\n"), filename, strerr
or(errno));
} vext = _get_ext_val (ext, add[0] - ext);
free(fullfn); if (max_levels) {
} if (((vext == 0x20202020) && (itemtype == GUI_ITEM_TYPE_PLAYLIST))
|| _is_known_ext (gui->playlist.exts[XUI_EXTS_PLAYLIST], vext)) {
int n = _gui_playlist_add_playlist (gui, mrlb, replace);
int mrl_look_like_file(char *mrl) { if (n > 0)
return n;
}
}
if(mrl && strlen(mrl)) { if (_gui_playlist_insert (gui, -1, start, lastpart, sub, 0, -1, 0, 0) < 0)
if((strncasecmp(mrl, "file:", 5)) &&
strstr (mrl, ":/") && (strstr (mrl, ":/") < strchr(mrl, '/')))
return 0; return 0;
gui->playlist.mmk[gui->playlist.num - 1]->type = type;
return 1;
} }
return 1; if (!max_levels)
} return 0;
void mediamark_collect_from_directory (gGui_t *gui, char *filepathname) {
DIR *dir;
struct dirent *dentry;
if((dir = opendir(filepathname))) {
while((dentry = readdir(dir))) {
char fullpathname[XITK_PATH_MAX + XITK_NAME_MAX + 2] = "";
snprintf(fullpathname, sizeof(fullpathname) - 1, "%s/%s", filepathname, de
ntry->d_name);
if(fullpathname[strlen(fullpathname) - 1] == '/')
fullpathname[strlen(fullpathname) - 1] = '\0';
if(is_a_dir(fullpathname)) {
if(!((strlen(dentry->d_name) == 1) && (dentry->d_name[0] == '.'))
&& !((strlen(dentry->d_name) == 2) &&
((dentry->d_name[0] == '.') && dentry->d_name[1] == '.'))) {
mediamark_collect_from_directory (gui, fullpathname);
}
}
else {
char *extension = strrchr(fullpathname, '.');
size_t ext_len = extension ? strlen(extension) : 0;
if (ext_len > 1 && ext_len < 7) {
char lo_ext[10];
size_t i;
for (i = 0; i < ext_len; i++) {
lo_ext[i] = tolower(extension[i]);
}
lo_ext[i++] = ' ';
lo_ext[i] = 0;
static const char valid_endings[] =
".pls .m3u .sfv .tox .asx .smi .smil .xml .fxd " /* Playlists */
".4xm .ac3 .aif .aiff .asf .wmv .wma .wvx .wax .aud .avi .cin .cpk
.cak "
".film .dv .dif .fli .flc .mjpg .mov .qt .m2p .mp4 .mp3 .mp2 .mpa .
mpega .mpg .mpeg "
".mpv .mve .mv8 .nsf .nsv .ogg .ogm .spx .pes .png .mng .pva .ra .r
m "
".ram .rmvb .roq .snd .au .str .iki .ik2 .dps .dat .xa .xa1 .xa2 .x
as .xap .ts .m2t "
".trp .vob .voc .vox .vqa .wav .wve .y4m ";
if (strstr(valid_endings, lo_ext)) { sarray = xine_sarray_new (512, _gui_mmk_cmp);
mediamark_append_entry (gui, fullpathname, fullpathname, NULL, 0, dupl = xine_sarray_new (512, _gui_playlist_dupl_cmp);
-1, 0, 0); n = 0;
} level = 0;
} *(add[level])++ = '/';
} dirs[level] = NULL;
num_subdirs[level] = 0;
gui_playlist_lock (gui);
old_num = gui->playlist.num;
while (1) {
struct dirent *entry;
char *stop;
/* enter pass 1 */
if (!dirs[level]) {
sort_start = gui->playlist.num;
add[level][0] = 0;
dirs[level] = opendir (start);
if (!dirs[level]) {
if (--level < 0)
break;
continue;
}
num_subdirs[level] = 0;
}
/* get entry */
entry = readdir (dirs[level]);
/* sort, then enter pass 2 or level up */
if (!entry) {
closedir (dirs[level]);
dirs[level] = NULL;
if (num_subdirs[level] >= 0) {
_gui_mmk_sort (sarray, gui->playlist.mmk + sort_start, gui->playlist.num
- sort_start);
if (num_subdirs[level] > 0) {
add[level][0] = 0;
dirs[level] = opendir (start);
if (dirs[level]) {
num_subdirs[level] = -1;
continue;
}
}
}
if (--level < 0)
break;
continue;
}
/* add entry name */
stop = add[level] + strlcpy (add[level], entry->d_name, end - add[level]);
if (stop >= end)
stop = end;
/* try to get info */
stop[0] = 0;
if (stat (start, &sbuf))
continue;
/* dir */
if (S_ISDIR (sbuf.st_mode)) {
if (add[level][0] == '.') {
if (!add[level][1] || ((add[level][1] == '.') && !add[level][2]))
continue;
}
if (num_subdirs[level] >= 0) { /* pass 1: files */
num_subdirs[level]++;
} else { /* pass 2: dirs */
if (level >= max_levels - 1)
continue;
add[level + 1] = stop;
level++;
*(add[level])++ = '/';
dirs[level] = NULL;
num_subdirs[level] = 0;
}
} else if (S_ISREG (sbuf.st_mode)) {
uint32_t vext, type;
if (num_subdirs[level] < 0)
continue;
mrlb->lastpart = add[level];
mrlb->args = mrlb->info = mrlb->end = stop;
{
char *ext;
add[level][-1] = '.';
for (ext = stop; ext[-1] != '.'; ext--) ;
add[level][-1] = '/';
if (ext <= add[level])
ext = stop;
mrlb->ext = ext;
vext = _get_ext_val (ext, stop - ext);
}
type = _is_known_ext (gui->playlist.exts[XUI_EXTS_PLAYLIST], vext) ? 1 : 0
;
/* playlist file ? */
if ((level < max_levels - 1) && type) {
int r = _gui_playlist_add_playlist (gui, mrlb, 0);
if (r > 0) {
n += r;
continue;
}
}
/* want all files ? */
if (!all_files) {
/* media file ? */
if (!type && _is_known_ext (gui->playlist.exts[XUI_EXTS_MEDIA], vext))
type = 2;
if (!type)
continue;
}
if (_gui_playlist_insert (gui, -1, start, add[level], NULL, add[0] - start
, -1, 0, 0) < 0)
continue;
gui->playlist.mmk[gui->playlist.num - 1]->from = MMK_FROM_DIR;
xine_sarray_add (dupl, gui->playlist.mmk[gui->playlist.num - 1]);
n++;
} }
closedir(dir);
} }
} {
int i, t;
/* we may have got some media files _and_ some playlists referencing them.
* playlist shall take effect, mark the duplicates with MMK_FROM_USER,
* which cannot happen here. */
for (i = old_num; i < gui->playlist.num; i++) {
if ((gui->playlist.mmk[i]->from == MMK_FROM_PLAYLIST) &&
!strncmp (gui->playlist.mmk[i]->mrl, start, add[0] - start)) {
int d_indx, real_start;
real_start = gui->playlist.mmk[i]->start;
gui->playlist.mmk[i]->start = add[0] - start;
d_indx = xine_sarray_binary_search (dupl, gui->playlist.mmk[i]);
gui->playlist.mmk[i]->start = real_start;
if (d_indx >= 0) {
mediamark_t *m = xine_sarray_get (dupl, d_indx);
m->from = MMK_FROM_USER;
}
}
}
/* comb out the duplicates, and reset the dupl sort hints */
for (t = i = old_num; i < gui->playlist.num; i++) {
if (gui->playlist.mmk[i]->from == MMK_FROM_DIR) {
gui->playlist.mmk[i]->start = 0;
gui->playlist.mmk[t++] = gui->playlist.mmk[i];
} else if (gui->playlist.mmk[i]->from == MMK_FROM_PLAYLIST) {
gui->playlist.mmk[t++] = gui->playlist.mmk[i];
} else /* MMK_FROM_USER */ {
mediamark_free (gui->playlist.mmk + i);
}
}
gui->playlist.num = t;
n = gui->playlist.num - old_num;
}
/* gui_playlist_unlock (gui);
* EDITOR
*/
static void _mmkedit_exit (xitk_widget_t *w, void *data, int state) {
xui_mmkedit_t *mmkedit = data;
(void)w; xine_sarray_delete (dupl);
(void)state; xine_sarray_delete (sarray);
mmkedit->visible = 0; return n;
gui_save_window_pos (mmkedit->gui, "mmk_editor", mmkedit->widget_key);
mmkedit->mmk = NULL;
xitk_unregister_event_handler (mmkedit->gui->xitk, &mmkedit->widget_key);
xitk_window_destroy_window (mmkedit->xwin);
mmkedit->xwin = NULL;
/* xitk_dlist_init (&mmkedit->widget_list.list); */
playlist_get_input_focus (mmkedit->gui);
mmkedit->gui->mmkedit = NULL;
free (mmkedit);
} }
static int mmkedit_event (void *data, const xitk_be_event_t *e) { /** gui mediamark editor window ************************************************
xui_mmkedit_t *mmkedit = data; ********/
switch (e->type) {
case XITK_EV_DEL_WIN:
_mmkedit_exit (NULL, mmkedit, 0);
return 1;
case XITK_EV_KEY_DOWN:
if ((e->utf8[0] == XITK_CTRL_KEY_PREFIX) && (e->utf8[1] == XITK_KEY_ESCAPE
)) {
_mmkedit_exit (NULL, mmkedit, 0);
return 1;
}
default: ;
}
return gui_handle_be_event (mmkedit->gui, e);
}
void mmk_editor_raise_window (gGui_t *gui) { void mmk_editor_raise_window (gGui_t *gui) {
if (gui && gui->mmkedit) if (gui && gui->mmkedit)
raise_window (gui, gui->mmkedit->xwin, gui->mmkedit->visible, 1); raise_window (gui, gui->mmkedit->xwin, gui->mmkedit->visible, 1);
} }
void mmk_editor_toggle_visibility (gGui_t *gui) { void mmk_editor_toggle_visibility (gGui_t *gui) {
if (gui && gui->mmkedit) if (gui && gui->mmkedit)
toggle_window (gui, gui->mmkedit->xwin, gui->mmkedit->widget_list, &gui->mmk edit->visible, 1); toggle_window (gui, gui->mmkedit->xwin, gui->mmkedit->widget_list, &gui->mmk edit->visible, 1);
} }
void mmk_editor_end (gGui_t *gui) { static int _mmkedit_pts_2_ms (int pts) {
if (gui && gui->mmkedit) return (pts + ((pts < 0) ? -45 : 45)) / 90;
_mmkedit_exit (NULL, gui->mmkedit, 0);
} }
static void _mmkedit_set_mmk (xui_mmkedit_t *mmkedit, mediamark_t **mmk) { static void _mmkedit_set_mmk (xui_mmkedit_t *mmkedit, mediamark_t **mmk) {
mmkedit->mmk = mmk; mmkedit->mmk = mmk;
xitk_inputtext_change_text (mmkedit->mrl, (*mmk)->mrl); mediamark_t *_mmk = *mmk;
xitk_inputtext_change_text (mmkedit->ident, (*mmk)->ident);
xitk_inputtext_change_text (mmkedit->sub, (*mmk)->sub); xitk_inputtext_change_text (mmkedit->mrl, _mmk->mrl);
xitk_intbox_set_value (mmkedit->start, (*mmk)->start); xitk_inputtext_change_text (mmkedit->ident, _mmk->ident);
xitk_intbox_set_value (mmkedit->end, (*mmk)->end); xitk_inputtext_change_text (mmkedit->sub, _mmk->sub);
xitk_intbox_set_value (mmkedit->av_offset, (*mmk)->av_offset); xitk_intbox_set_value (mmkedit->start, mmkedit->vals[0] = _mmk->start);
xitk_intbox_set_value (mmkedit->spu_offset, (*mmk)->spu_offset); xitk_intbox_set_value (mmkedit->end, mmkedit->vals[1] = _mmk->end);
xitk_intbox_set_value (mmkedit->av_offset, mmkedit->vals[2] = _mmkedit_pts_2_
ms (_mmk->av_offset));
xitk_intbox_set_value (mmkedit->spu_offset, mmkedit->vals[3] = _mmkedit_pts_2_
ms (_mmk->spu_offset));
} }
void mmk_editor_set_mmk (gGui_t *gui, mediamark_t **mmk) { void mmk_editor_set_mmk (gGui_t *gui, mediamark_t **mmk) {
if (gui && gui->mmkedit) if (gui && gui->mmkedit)
_mmkedit_set_mmk (gui->mmkedit, mmk); _mmkedit_set_mmk (gui->mmkedit, mmk);
} }
static void _mmkedit_apply (xitk_widget_t *w, void *data, int state) { static void _mmkedit_btn (xitk_widget_t *w, void *data, int state) {
xui_mmkedit_t *mmkedit = data; xui_mmkedit_t *mmkedit = data;
(void)w;
(void)state; (void)state;
if (mmkedit->mmk) { if ((w != mmkedit->close) && mmkedit->mmk) {
const char *r, *sub; const char *r;
char *ident, *mrl; char buf[2048];
int start, end, av_offset, spu_offset;
r = xitk_inputtext_get_text (mmkedit->mrl); r = xitk_inputtext_get_text (mmkedit->mrl);
if (r && r[0]) { if (r && r[0]) {
mrl = strdup (r); strlcpy (buf, r, sizeof (buf));
str_unquote (mrl); str_unquote (buf);
} else { mediamark_set_str_val (mmkedit->mmk, buf, MMK_VAL_MRL);
mrl = strdup ((*mmkedit->mmk)->mrl);
} }
r = xitk_inputtext_get_text (mmkedit->ident); r = xitk_inputtext_get_text (mmkedit->ident);
if (r && r[0]) { if (r && r[0]) {
ident = strdup (r); strlcpy (buf, r, sizeof (buf));
str_unquote (ident); str_unquote (buf);
} else { r = buf;
ident = strdup (mrl);
} }
mediamark_set_str_val (mmkedit->mmk, r, MMK_VAL_IDENT);
sub = xitk_inputtext_get_text (mmkedit->sub); r = xitk_inputtext_get_text (mmkedit->sub);
if (sub && (!sub[0])) mediamark_set_str_val (mmkedit->mmk, r, MMK_VAL_SUB);
sub = NULL;
if ((start = xitk_intbox_get_value (mmkedit->start)) < 0) if (mmkedit->vals[0] < 0)
start = 0; mmkedit->vals[0] = 0;
if ((end = xitk_intbox_get_value (mmkedit->end)) <= -1) if (mmkedit->vals[1] <= -1)
end = -1; mmkedit->vals[1] = -1;
else if (end < start) else if (mmkedit->vals[1] < mmkedit->vals[0])
end = start + 1; mmkedit->vals[1] = mmkedit->vals[0] + 1;
av_offset = xitk_intbox_get_value (mmkedit->av_offset); (*mmkedit->mmk)->start = mmkedit->vals[0];
spu_offset = xitk_intbox_get_value (mmkedit->spu_offset); (*mmkedit->mmk)->end = mmkedit->vals[1];
(*mmkedit->mmk)->av_offset = mmkedit->vals[2] * 90;
(*mmkedit->mmk)->spu_offset = mmkedit->vals[3] * 90;
xitk_widgets_state (&mmkedit->apply, 1, XITK_WIDGET_STATE_ENABLE, 0);
mediamark_replace_entry (mmkedit->mmk, mrl, ident, sub, start, end, av_offse t, spu_offset);
if (mmkedit->callback) if (mmkedit->callback)
mmkedit->callback (mmkedit->user_data); mmkedit->callback (mmkedit->user_data);
}
free (mrl); if (w != mmkedit->apply) {
free (ident); mmkedit->visible = 0;
gui_save_window_pos (mmkedit->gui, "mmk_editor", mmkedit->widget_key);
mmkedit->mmk = NULL;
xitk_unregister_event_handler (mmkedit->gui->xitk, &mmkedit->widget_key);
xitk_window_destroy_window (mmkedit->xwin);
mmkedit->xwin = NULL;
/* xitk_dlist_init (&mmkedit->widget_list.list); */
playlist_get_input_focus (mmkedit->gui);
mmkedit->gui->mmkedit = NULL;
free (mmkedit);
} }
} }
static void _mmkedit_ok (xitk_widget_t *w, void *data, int state) { static int mmkedit_event (void *data, const xitk_be_event_t *e) {
xui_mmkedit_t *mmkedit = (xui_mmkedit_t *)data; xui_mmkedit_t *mmkedit = data;
(void)w; switch (e->type) {
_mmkedit_apply (NULL, mmkedit, state); case XITK_EV_DEL_WIN:
_mmkedit_exit (NULL, mmkedit, state); _mmkedit_btn (mmkedit->close, mmkedit, 0);
return 1;
case XITK_EV_KEY_DOWN:
if ((e->utf8[0] == XITK_CTRL_KEY_PREFIX) && (e->utf8[1] == XITK_KEY_ESCAPE
)) {
_mmkedit_btn (mmkedit->close, mmkedit, 0);
return 1;
}
default: ;
}
return gui_handle_be_event (mmkedit->gui, e);
}
void mmk_editor_end (gGui_t *gui) {
if (gui && gui->mmkedit)
_mmkedit_btn (gui->mmkedit->close, gui->mmkedit, 0);
} }
static void mmk_fileselector_callback (filebrowser_t *fb, void *data) { static void mmk_fileselector_callback (filebrowser_t *fb, void *data) {
xui_mmkedit_t *mmkedit = data; xui_mmkedit_t *mmkedit = data;
char *file, *dir; char *file, *dir;
if ((dir = filebrowser_get_current_dir (fb)) != NULL) { if ((dir = filebrowser_get_current_dir (fb)) != NULL) {
strlcpy (mmkedit->gui->curdir, dir, sizeof (mmkedit->gui->curdir)); strlcpy (mmkedit->gui->curdir, dir, sizeof (mmkedit->gui->curdir));
free (dir); free (dir);
} }
skipping to change at line 3013 skipping to change at line 3759
if(mrl_look_like_file(path)) { if(mrl_look_like_file(path)) {
char *p; char *p;
open_path = strdup(path); open_path = strdup(path);
if(!strncasecmp(path, "file:", 5)) if(!strncasecmp(path, "file:", 5))
path += 5; path += 5;
p = strrchr(open_path, '/'); p = strrchr(open_path, '/');
if (p && strlen(p)) if (p && p[0])
*p = '\0'; *p = '\0';
} }
else else
open_path = strdup (mmkedit->gui->curdir); open_path = strdup (mmkedit->gui->curdir);
create_filebrowser (mmkedit->gui, _("Pick a subtitle file"), open_path, hidden _file_cb, mmkedit->gui, &cbb, NULL, NULL); create_filebrowser (mmkedit->gui, _("Pick a subtitle file"), open_path, hidden _file_cb, mmkedit->gui, &cbb, NULL, NULL);
free(open_path); free(open_path);
} }
static void _mmk_edit_set_val (xitk_widget_t *w, void *data, int value) {
uint8_t *land = (uint8_t *)data;
xui_mmkedit_t *mmkedit;
uint32_t i = *land;
(void)w;
land -= i;
xitk_container (mmkedit, land, helipad[0]);
mmkedit->vals[i] = value;
xitk_widgets_state (&mmkedit->apply, 1, XITK_WIDGET_STATE_ENABLE, ~0u);
}
static void _mmk_edit_set_str (xitk_widget_t *w, void *data, const char *str) {
xui_mmkedit_t *mmkedit = (xui_mmkedit_t *)data;
(void)w;
(void)str;
xitk_widgets_state (&mmkedit->apply, 1, XITK_WIDGET_STATE_ENABLE, ~0u);
}
void mmk_edit_mediamark (gGui_t *gui, mediamark_t **mmk, apply_callback_t callba ck, void *data) { void mmk_edit_mediamark (gGui_t *gui, mediamark_t **mmk, apply_callback_t callba ck, void *data) {
xui_mmkedit_t *mmkedit; xui_mmkedit_t *mmkedit;
xitk_widget_t *b; xitk_widget_t *b;
int x, y, w; int x, y, w;
if (!gui) if (!gui)
return; return;
mmkedit = gui->mmkedit; mmkedit = gui->mmkedit;
if (mmkedit) { if (mmkedit) {
skipping to change at line 3087 skipping to change at line 3853
x += w + 5; x += w + 5;
xitk_image_draw_outter_frame (bg, _("A/V offset"), btnfontname, x, y, w, 45) ; xitk_image_draw_outter_frame (bg, _("A/V offset"), btnfontname, x, y, w, 45) ;
x += w + 5; x += w + 5;
xitk_image_draw_outter_frame (bg, _("SPU offset"), btnfontname, x, y, w, 45) ; xitk_image_draw_outter_frame (bg, _("SPU offset"), btnfontname, x, y, w, 45) ;
xitk_window_set_background_image (mmkedit->xwin, bg); xitk_window_set_background_image (mmkedit->xwin, bg);
} }
{ {
xitk_inputtext_widget_t inp; xitk_inputtext_widget_t inp;
XITK_WIDGET_INIT (&inp); inp.nw.wl = mmkedit->widget_list;
inp.skin_element_name = NULL; inp.nw.skin_element_name = NULL;
inp.text = NULL; inp.nw.userdata = mmkedit;
inp.max_length = 2048; inp.text = NULL;
inp.callback = NULL; inp.max_length = 2048;
inp.userdata = NULL; inp.callback = _mmk_edit_set_str;
x = 15; x = 15;
y = 34 - 6; y = 34 - 6;
w = WINDOW_WIDTH - 30; w = WINDOW_WIDTH - 30;
mmkedit->ident = xitk_noskin_inputtext_create (mmkedit->widget_list, &inp, mmkedit->ident = xitk_noskin_inputtext_create (&inp,
x + 10, y + 16, w - 20, 20, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, fontname); x + 10, y + 16, w - 20, 20, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, fontname);
xitk_add_widget (mmkedit->widget_list, mmkedit->ident, XITK_WIDGET_STATE_ENA BLE | XITK_WIDGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, mmkedit->ident, XITK_WIDGET_STATE_ENA BLE | XITK_WIDGET_STATE_VISIBLE);
xitk_set_widget_tips (mmkedit->ident, _("Mediamark Identifier")); xitk_set_widget_tips (mmkedit->ident, _("Mediamark Identifier"));
y += 45 + 3; y += 45 + 3;
mmkedit->mrl = xitk_noskin_inputtext_create (mmkedit->widget_list, &inp, mmkedit->mrl = xitk_noskin_inputtext_create (&inp,
x + 10, y + 16, w - 20, 20, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, fontname); x + 10, y + 16, w - 20, 20, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, fontname);
xitk_add_widget (mmkedit->widget_list, mmkedit->mrl, XITK_WIDGET_STATE_ENABL E | XITK_WIDGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, mmkedit->mrl, XITK_WIDGET_STATE_ENABL E | XITK_WIDGET_STATE_VISIBLE);
xitk_set_widget_tips (mmkedit->mrl, _("Mediamark Mrl")); xitk_set_widget_tips (mmkedit->mrl, _("Mediamark Mrl"));
y += 45 + 3; y += 45 + 3;
mmkedit->sub = xitk_noskin_inputtext_create (mmkedit->widget_list, &inp, mmkedit->sub = xitk_noskin_inputtext_create (&inp,
x + 10, y + 16, w - 20 - 100 - 10, 20, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_ TEXT_NORM, fontname); x + 10, y + 16, w - 20 - 100 - 10, 20, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_ TEXT_NORM, fontname);
xitk_add_widget (mmkedit->widget_list, mmkedit->sub, XITK_WIDGET_STATE_ENABL E | XITK_WIDGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, mmkedit->sub, XITK_WIDGET_STATE_ENABL E | XITK_WIDGET_STATE_VISIBLE);
xitk_set_widget_tips (mmkedit->sub, _("Subtitle File")); xitk_set_widget_tips (mmkedit->sub, _("Subtitle File"));
} }
{ {
xitk_labelbutton_widget_t lb; xitk_labelbutton_widget_t lb;
xitk_intbox_widget_t ib; xitk_intbox_widget_t ib;
XITK_WIDGET_INIT (&lb); lb.nw.wl = mmkedit->widget_list;
lb.skin_element_name = NULL; lb.nw.skin_element_name = NULL;
lb.nw.userdata = mmkedit;
lb.button_type = CLICK_BUTTON; lb.button_type = CLICK_BUTTON;
lb.align = ALIGN_CENTER; lb.align = ALIGN_CENTER;
lb.state_callback = NULL; lb.state_callback = NULL;
lb.userdata = mmkedit;
XITK_WIDGET_INIT (&ib); ib.nw.wl = mmkedit->widget_list;
ib.skin_element_name = NULL; ib.nw.skin_element_name = NULL;
ib.fmt = INTBOX_FMT_DECIMAL; ib.callback = _mmk_edit_set_val;
ib.callback = NULL; memcpy (mmkedit->helipad, "\x00\x01\x02\x03", 4);
ib.userdata = NULL;
ib.step = 1; lb.label = _("Sub File");
lb.callback = _mmkedit_select_sub;
lb.label = _("Sub File"); b = xitk_noskin_labelbutton_create (&lb,
lb.callback = _mmkedit_select_sub;
b = xitk_noskin_labelbutton_create (mmkedit->widget_list, &lb,
x + 10 + w - 20 - 100, y + 16, 100, 20, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN _TEXT_NORM, XITK_NOSKIN_TEXT_INV, btnfontname); x + 10 + w - 20 - 100, y + 16, 100, 20, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN _TEXT_NORM, XITK_NOSKIN_TEXT_INV, btnfontname);
xitk_add_widget (mmkedit->widget_list, b, XITK_WIDGET_STATE_ENABLE | XITK_WI DGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, b, XITK_WIDGET_STATE_ENABLE | XITK_WI DGET_STATE_VISIBLE);
xitk_set_widget_tips (b, _("Select a subtitle file to use together with the mrl.")); xitk_set_widget_tips (b, _("Select a subtitle file to use together with the mrl."));
y += 45 + 3; y += 45 + 3;
w = 120; w = 120;
ib.min = 0; ib.min = 0;
ib.max = 0; ib.max = 0;
ib.value = 0; ib.value = 0;
mmkedit->start = xitk_noskin_intbox_create (mmkedit->widget_list, &ib, ib.step = 1;
x + 30, y + 16, w - 60, 20); ib.fmt = INTBOX_FMT_SECONDS;
ib.nw.userdata = &mmkedit->helipad[0];
mmkedit->start = xitk_noskin_intbox_create (&ib, x + 20, y + 16, w - 40, 20)
;
xitk_add_widget (mmkedit->widget_list, mmkedit->start, XITK_WIDGET_STATE_ENA BLE | XITK_WIDGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, mmkedit->start, XITK_WIDGET_STATE_ENA BLE | XITK_WIDGET_STATE_VISIBLE);
xitk_set_widget_tips (mmkedit->start, _("Mediamark start time (secs).")); xitk_set_widget_tips (mmkedit->start, _("Mediamark start time (secs)."));
x += w + 5; x += w + 5;
ib.value = -1; ib.value = -1;
mmkedit->end = xitk_noskin_intbox_create (mmkedit->widget_list, &ib, ib.nw.userdata = &mmkedit->helipad[1];
x + 30, y + 16, w - 60, 20); mmkedit->end = xitk_noskin_intbox_create (&ib, x + 20, y + 16, w - 40, 20);
xitk_add_widget (mmkedit->widget_list, mmkedit->end, XITK_WIDGET_STATE_ENABL E | XITK_WIDGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, mmkedit->end, XITK_WIDGET_STATE_ENABL E | XITK_WIDGET_STATE_VISIBLE);
xitk_set_widget_tips (mmkedit->end, _("Mediamark end time (secs).")); xitk_set_widget_tips (mmkedit->end, _("Mediamark end time (secs)."));
x += w + 5; x += w + 5;
ib.value = 0; ib.value = 0;
mmkedit->av_offset = xitk_noskin_intbox_create (mmkedit->widget_list, &ib, ib.step = 40;
x + 30, y + 16, w - 60, 20); ib.fmt = INTBOX_FMT_MILLISECS;
ib.nw.userdata = &mmkedit->helipad[2];
mmkedit->av_offset = xitk_noskin_intbox_create (&ib, x + 20, y + 16, w - 40,
20);
xitk_add_widget (mmkedit->widget_list, mmkedit->av_offset, XITK_WIDGET_STATE _ENABLE | XITK_WIDGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, mmkedit->av_offset, XITK_WIDGET_STATE _ENABLE | XITK_WIDGET_STATE_VISIBLE);
xitk_set_widget_tips (mmkedit->av_offset, _("Offset of Audio and Video.")); xitk_set_widget_tips (mmkedit->av_offset, _("Offset of Audio and Video."));
x += w + 5; x += w + 5;
ib.value = 0; ib.value = 0;
mmkedit->spu_offset = xitk_noskin_intbox_create (mmkedit->widget_list, &ib, ib.nw.userdata = &mmkedit->helipad[3];
x + 30, y + 16, w - 60, 20); mmkedit->spu_offset = xitk_noskin_intbox_create (&ib, x + 20, y + 16, w - 40
, 20);
xitk_add_widget (mmkedit->widget_list, mmkedit->spu_offset, XITK_WIDGET_STAT E_ENABLE | XITK_WIDGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, mmkedit->spu_offset, XITK_WIDGET_STAT E_ENABLE | XITK_WIDGET_STATE_VISIBLE);
xitk_set_widget_tips (mmkedit->spu_offset, _("Subpicture offset.")); xitk_set_widget_tips (mmkedit->spu_offset, _("Subpicture offset."));
y = WINDOW_HEIGHT - (23 + 15); y = WINDOW_HEIGHT - (23 + 15);
x = 15; x = 15;
lb.label = _("OK"); lb.label = _("OK");
lb.callback = _mmkedit_ok; lb.callback = _mmkedit_btn;
b = xitk_noskin_labelbutton_create (mmkedit->widget_list, mmkedit->ok = b = xitk_noskin_labelbutton_create (&lb,
&lb, x, y, 100, 23, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, XITK_NOS x, y, 100, 23, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_T
KIN_TEXT_INV, btnfontname); EXT_INV, btnfontname);
xitk_add_widget (mmkedit->widget_list, b, XITK_WIDGET_STATE_ENABLE | XITK_WI DGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, b, XITK_WIDGET_STATE_ENABLE | XITK_WI DGET_STATE_VISIBLE);
xitk_set_widget_tips (b, _("Apply the changes and close the window.")); xitk_set_widget_tips (b, _("Apply the changes and close the window."));
x = (WINDOW_WIDTH - 100) / 2; x = (WINDOW_WIDTH - 100) / 2;
lb.label = _("Apply"); lb.label = _("Apply");
lb.callback = _mmkedit_apply; mmkedit->apply = b = xitk_noskin_labelbutton_create (&lb,
b = xitk_noskin_labelbutton_create (mmkedit->widget_list, x, y, 100, 23, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_T
&lb, x, y, 100, 23, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, XITK_NOS EXT_INV, btnfontname);
KIN_TEXT_INV, btnfontname); xitk_add_widget (mmkedit->widget_list, b, /* XITK_WIDGET_STATE_ENABLE | */ X
xitk_add_widget (mmkedit->widget_list, b, XITK_WIDGET_STATE_ENABLE | XITK_WI ITK_WIDGET_STATE_VISIBLE);
DGET_STATE_VISIBLE);
xitk_set_widget_tips (b, _("Apply the changes to the playlist.")); xitk_set_widget_tips (b, _("Apply the changes to the playlist."));
x = WINDOW_WIDTH - (100 + 15); x = WINDOW_WIDTH - (100 + 15);
lb.label = _("Close"); lb.label = _("Close");
lb.callback = _mmkedit_exit; mmkedit->close = b = xitk_noskin_labelbutton_create (&lb,
b = xitk_noskin_labelbutton_create (mmkedit->widget_list, x, y, 100, 23, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_T
&lb, x, y, 100, 23, XITK_NOSKIN_TEXT_NORM, XITK_NOSKIN_TEXT_NORM, XITK_NOS EXT_INV, btnfontname);
KIN_TEXT_INV, btnfontname);
xitk_add_widget (mmkedit->widget_list, b, XITK_WIDGET_STATE_ENABLE | XITK_WI DGET_STATE_VISIBLE); xitk_add_widget (mmkedit->widget_list, b, XITK_WIDGET_STATE_ENABLE | XITK_WI DGET_STATE_VISIBLE);
xitk_set_widget_tips (b, _("Discard changes and dismiss the window.")); xitk_set_widget_tips (b, _("Discard changes and dismiss the window."));
} }
mmkedit->widget_key = xitk_be_register_event_handler ("gui->mmkedit", mmkedit- >xwin, mmkedit_event, mmkedit, NULL, NULL); mmkedit->widget_key = xitk_be_register_event_handler ("gui->mmkedit", mmkedit- >xwin, mmkedit_event, mmkedit, NULL, NULL);
mmkedit->visible = 1; mmkedit->visible = 1;
_mmkedit_set_mmk (mmkedit, mmk); _mmkedit_set_mmk (mmkedit, mmk);
raise_window (mmkedit->gui, mmkedit->xwin, 1, 1); raise_window (mmkedit->gui, mmkedit->xwin, 1, 1);
xitk_window_set_input_focus (mmkedit->xwin); xitk_window_set_input_focus (mmkedit->xwin);
 End of changes. 307 change blocks. 
1541 lines changed or deleted 2327 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)