Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
4c0b7973
Commit
4c0b7973
authored
Sep 29, 2013
by
Reka Inovan
Committed by
Jean-Baptiste Kempf
Oct 12, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rewrites asx file support using vlc_xml API
Signed-off-by:
Jean-Baptiste Kempf
<
jb@videolan.org
>
parent
ab81a846
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
297 additions
and
630 deletions
+297
-630
modules/demux/playlist/asx.c
modules/demux/playlist/asx.c
+297
-630
No files found.
modules/demux/playlist/asx.c
View file @
4c0b7973
/*****************************************************************************
/*****************************************************************************
* asx.c : ASX playlist format import
* asx.c : ASX playlist format import
*****************************************************************************
*****************************************************************************
* Copyright (C) 2005-20
06
VLC authors and VideoLAN
* Copyright (C) 2005-20
13
VLC authors and VideoLAN
* $Id$
* $Id$
*
*
* Authors: Derk-Jan Hartman <hartman at videolan dot org>
* Authors: Derk-Jan Hartman <hartman at videolan dot org>
...
@@ -21,7 +21,8 @@
...
@@ -21,7 +21,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
*****************************************************************************/
/* See also: http://msdn.microsoft.com/library/en-us/wmplay10/mmp_sdk/windowsmediametafilereference.asp
/* See also:
* http://msdn.microsoft.com/en-us/library/windows/desktop/dd564668.aspx
*/
*/
/*****************************************************************************
/*****************************************************************************
...
@@ -33,19 +34,15 @@
...
@@ -33,19 +34,15 @@
#include <vlc_common.h>
#include <vlc_common.h>
#include <vlc_demux.h>
#include <vlc_demux.h>
#include <vlc_xml.h>
#include <vlc_strings.h>
#include <ctype.h>
#include <ctype.h>
#include <vlc_charset.h>
#include "playlist.h"
#include "playlist.h"
#include <vlc_meta.h>
struct
demux_sys_t
struct
demux_sys_t
{
{
char
*
psz_prefix
;
char
*
psz_data
;
int64_t
i_data_len
;
bool
b_utf8
;
bool
b_skip_ads
;
};
};
/*****************************************************************************
/*****************************************************************************
...
@@ -53,721 +50,391 @@ struct demux_sys_t
...
@@ -53,721 +50,391 @@ struct demux_sys_t
*****************************************************************************/
*****************************************************************************/
static
int
Demux
(
demux_t
*
p_demux
);
static
int
Demux
(
demux_t
*
p_demux
);
static
int
StoreString
(
demux_t
*
p_demux
,
char
**
ppsz_string
,
static
mtime_t
ParseTime
(
xml_reader_t
*
p_xml_reader
)
const
char
*
psz_source_start
,
const
char
*
psz_source_end
)
{
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
char
*
psz_value
=
NULL
;
unsigned
len
=
psz_source_end
-
psz_source_start
;
char
*
psz_start
=
NULL
;
free
(
*
ppsz_string
);
const
char
*
psz_node
=
NULL
;
const
char
*
psz_txt
=
NULL
;
char
*
buf
=
*
ppsz_string
=
malloc
((
len
*
(
1
+
!
p_sys
->
b_utf8
))
+
1
);
int
i_subfractions
=
-
1
;
if
(
buf
==
NULL
)
return
VLC_ENOMEM
;
if
(
p_sys
->
b_utf8
)
int
i_subresult
=
0
;
{
mtime_t
i_result
=
0
;
memcpy
(
buf
,
psz_source_start
,
len
);
(
*
ppsz_string
)[
len
]
=
'\0'
;
EnsureUTF8
(
*
ppsz_string
);
}
else
{
/* Latin-1 -> UTF-8 */
for
(
unsigned
i
=
0
;
i
<
len
;
i
++
)
{
unsigned
char
c
=
psz_source_start
[
i
];
if
(
c
&
0x80
)
{
*
buf
++
=
0xc0
|
(
c
>>
6
);
*
buf
++
=
0x80
|
(
c
&
0x3f
);
}
else
*
buf
++
=
c
;
}
*
buf
++
=
'\0'
;
buf
=
realloc
(
*
ppsz_string
,
buf
-
*
ppsz_string
);
do
if
(
buf
)
{
*
ppsz_string
=
buf
;
psz_txt
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
psz_node
)
;
}
}
return
VLC_SUCCESS
;
while
(
psz_txt
&&
strncasecmp
(
psz_txt
,
"VALUE"
,
5
)
);
}
static
char
*
SkipBlanks
(
char
*
s
,
size_t
i_strlen
)
psz_value
=
strdup
(
psz_node
);
{
psz_start
=
psz_value
;
while
(
i_strlen
>
0
)
{
switch
(
*
s
)
{
case
' '
:
case
'\t'
:
case
'\r'
:
case
'\n'
:
--
i_strlen
;
++
s
;
break
;
default:
i_strlen
=
0
;
}
}
return
s
;
}
static
int
ParseTime
(
char
*
s
,
size_t
i_strlen
)
while
(
*
psz_value
)
{
// need to parse hour:minutes:sec.fraction string
int
result
=
0
;
int
val
;
const
char
*
end
=
s
+
i_strlen
;
// skip leading spaces if any
s
=
SkipBlanks
(
s
,
i_strlen
);
val
=
0
;
while
(
(
s
<
end
)
&&
isdigit
((
unsigned
char
)
*
s
)
)
{
{
int
newval
=
val
*
10
+
(
*
s
-
'0'
);
if
(
isdigit
(
*
psz_value
)
)
if
(
newval
<
val
)
{
{
// overflow
i_subresult
=
i_subresult
*
10
;
val
=
0
;
i_subresult
+=
*
psz_value
-
'0'
;
break
;
if
(
i_subfractions
!=
-
1
)
i_subfractions
++
;
}
}
val
=
newval
;
else
if
(
*
psz_value
==
':'
)
++
s
;
}
result
=
val
;
s
=
SkipBlanks
(
s
,
end
-
s
);
if
(
*
s
==
':'
)
{
++
s
;
s
=
SkipBlanks
(
s
,
end
-
s
);
result
=
result
*
60
;
val
=
0
;
while
(
(
s
<
end
)
&&
isdigit
((
unsigned
char
)
*
s
)
)
{
{
int
newval
=
val
*
10
+
(
*
s
-
'0'
);
i_result
+=
i_subresult
;
if
(
newval
<
val
)
i_result
=
i_result
*
60
;
{
i_subresult
=
0
;
// overflow
val
=
0
;
break
;
}
val
=
newval
;
++
s
;
}
}
result
+=
val
;
else
if
(
*
psz_value
==
'.'
)
s
=
SkipBlanks
(
s
,
end
-
s
);
if
(
*
s
==
':'
)
{
{
++
s
;
i_subfractions
=
0
;
s
=
SkipBlanks
(
s
,
end
-
s
);
i_result
+=
i_subresult
;
result
=
result
*
60
;
i_subresult
=
0
;
val
=
0
;
while
(
(
s
<
end
)
&&
isdigit
((
unsigned
char
)
*
s
)
)
{
int
newval
=
val
*
10
+
(
*
s
-
'0'
);
if
(
newval
<
val
)
{
// overflow
val
=
0
;
break
;
}
val
=
newval
;
++
s
;
}
result
+=
val
;
// TODO: one day, we may need to parse fraction for sub-second resolution
}
}
psz_value
++
;
}
if
(
i_subfractions
==
-
1
)
i_result
+=
i_subresult
;
/* Convert to microseconds */
if
(
i_subfractions
==
-
1
)
i_subfractions
=
0
;
while
(
i_subfractions
<
6
)
{
i_subresult
=
i_subresult
*
10
;
i_subfractions
++
;
}
}
return
result
;
i_result
=
i_result
*
1000000
;
if
(
i_subfractions
!=
-
1
)
i_result
+=
i_subresult
;
free
(
psz_start
);
return
i_result
;
}
static
void
ReadElement
(
xml_reader_t
*
p_xml_reader
,
char
**
ppsz_txt
)
{
const
char
*
psz_node
=
NULL
;
/* Read the text node */
xml_ReaderNextNode
(
p_xml_reader
,
&
psz_node
);
free
(
*
ppsz_txt
);
*
ppsz_txt
=
strdup
(
psz_node
);
resolve_xml_special_chars
(
*
ppsz_txt
);
/* Read the end element */
xml_ReaderNextNode
(
p_xml_reader
,
&
psz_node
);
/* TODO :
* Currently we don't check the agreement of start and end element
* This function is only used to read the element that cannot have child
* according to the reference.
*/
}
}
/*****************************************************************************
/*****************************************************************************
* Import_ASX: main import function
* Import_ASX: main import function
*****************************************************************************/
*****************************************************************************/
int
Import_ASX
(
vlc_object_t
*
p_this
)
int
Import_ASX
(
vlc_object_t
*
p_this
)
{
{
demux_t
*
p_demux
=
(
demux_t
*
)
p_this
;
demux_t
*
p_demux
=
(
demux_t
*
)
p_this
;
const
uint8_t
*
p_peek
;
CHECK_PEEK
(
p_peek
,
10
);
// skip over possible leading empty lines and empty spaces
p_peek
=
(
uint8_t
*
)
SkipBlanks
((
char
*
)
p_peek
,
6
);
if
(
POKE
(
p_peek
,
"<asx"
,
4
)
||
demux_IsPathExtension
(
p_demux
,
".asx"
)
||
if
(
demux_IsPathExtension
(
p_demux
,
".asx"
)
||
demux_IsPathExtension
(
p_demux
,
".wax"
)
||
demux_IsPathExtension
(
p_demux
,
".wvx"
)
||
demux_IsPathExtension
(
p_demux
,
".wax"
)
||
demux_IsPathExtension
(
p_demux
,
".wvx"
)
||
demux_IsForced
(
p_demux
,
"asx-open"
)
)
demux_IsForced
(
p_demux
,
"asx-open"
)
)
{
{
;
STANDARD_DEMUX_INIT_MSG
(
"found valid ASX playlist"
);
return
VLC_SUCCESS
;
}
}
else
else
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
STANDARD_DEMUX_INIT_MSG
(
"found valid ASX playlist"
);
p_demux
->
p_sys
->
psz_prefix
=
FindPrefix
(
p_demux
);
p_demux
->
p_sys
->
psz_data
=
NULL
;
p_demux
->
p_sys
->
i_data_len
=
-
1
;
p_demux
->
p_sys
->
b_utf8
=
false
;
p_demux
->
p_sys
->
b_skip_ads
=
var_InheritBool
(
p_demux
,
"playlist-skip-ads"
);
return
VLC_SUCCESS
;
}
}
/*****************************************************************************
/*****************************************************************************
* Deactivate: frees unused data
* Deactivate: frees unused data
*****************************************************************************/
*****************************************************************************/
void
Close_ASX
(
vlc_object_t
*
p_this
)
void
Close_ASX
(
vlc_object_t
*
p_this
)
{
{
demux_t
*
p_demux
=
(
demux_t
*
)
p_this
;
demux_t
*
p_demux
=
(
demux_t
*
)
p_this
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
free
(
p_sys
->
psz_prefix
);
free
(
p_sys
->
psz_data
);
free
(
p_sys
);
free
(
p_sys
);
}
}
static
int
Demux
(
demux_t
*
p_demux
)
static
void
ProcessEntry
(
int
*
pi_n_entry
,
xml_reader_t
*
p_xml_reader
,
input_item_node_t
*
p_subitems
,
input_item_t
*
p_current_input
,
char
*
psz_prefix
)
{
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
const
char
*
psz_node
=
NULL
;
char
*
psz_parse
=
NULL
;
const
char
*
psz_txt
=
NULL
;
char
*
psz_backup
=
NULL
;
int
i_type
;
bool
b_entry
=
false
;
input_item_t
*
p_current_input
=
GetCurrentItem
(
p_demux
);
char
*
psz_title
=
NULL
;
char
*
psz_artist
=
NULL
;
/* init txt */
char
*
psz_copyright
=
NULL
;
if
(
p_sys
->
i_data_len
<
0
)
char
*
psz_moreinfo
=
NULL
;
char
*
psz_description
=
NULL
;
char
*
psz_name
=
NULL
;
char
*
psz_mrl
=
NULL
;
char
*
psz_href
=
NULL
;
input_item_t
*
p_entry
=
NULL
;
int
i_options
;
mtime_t
i_start
=
0
;
mtime_t
i_duration
=
0
;
char
*
ppsz_options
[
2
];
do
{
{
int64_t
i_pos
=
0
;
i_type
=
xml_ReaderNextNode
(
p_xml_reader
,
&
psz_node
);
p_sys
->
i_data_len
=
stream_Size
(
p_demux
->
s
)
+
1
;
/* This is a cheat to prevent unnecessary realloc */
if
(
p_sys
->
i_data_len
<=
0
||
p_sys
->
i_data_len
>
16384
)
p_sys
->
i_data_len
=
1024
;
p_sys
->
psz_data
=
xmalloc
(
p_sys
->
i_data_len
+
1
);
/* load the complete file */
for
(
;;
)
{
int
i_read
=
stream_Read
(
p_demux
->
s
,
&
p_sys
->
psz_data
[
i_pos
],
p_sys
->
i_data_len
-
i_pos
);
p_sys
->
psz_data
[
i_pos
+
i_read
]
=
'\0'
;
if
(
i_read
<
p_sys
->
i_data_len
-
i_pos
)
break
;
/* Done */
i_pos
+=
i_read
;
p_sys
->
i_data_len
<<=
1
;
p_sys
->
psz_data
=
xrealloc
(
p_sys
->
psz_data
,
p_sys
->
i_data_len
*
sizeof
(
char
*
)
+
1
);
}
if
(
p_sys
->
i_data_len
<=
0
)
return
-
1
;
}
input_item_node_t
*
p_subitems
=
input_item_node_Create
(
p_current_input
);
if
(
i_type
==
XML_READER_STARTELEM
)
psz_parse
=
p_sys
->
psz_data
;
/* Find first element */
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"<ASX"
)
)
)
{
/* ASX element */
char
*
psz_string
=
NULL
;
int
i_strlen
=
0
;
char
*
psz_base_asx
=
NULL
;
char
*
psz_title_asx
=
NULL
;
char
*
psz_artist_asx
=
NULL
;
char
*
psz_copyright_asx
=
NULL
;
char
*
psz_moreinfo_asx
=
NULL
;
char
*
psz_abstract_asx
=
NULL
;
char
*
psz_base_entry
=
NULL
;
char
*
psz_title_entry
=
NULL
;
char
*
psz_artist_entry
=
NULL
;
char
*
psz_copyright_entry
=
NULL
;
char
*
psz_moreinfo_entry
=
NULL
;
char
*
psz_abstract_entry
=
NULL
;
int
i_entry_count
=
0
;
bool
b_skip_entry
=
false
;
char
*
psz_href
=
NULL
;
int
i_starttime
=
0
;
int
i_duration
=
0
;
psz_parse
=
strcasestr
(
psz_parse
,
">"
);
/* counter for single ad item */
input_item_t
*
uniq_entry_ad_backup
=
NULL
;
int
i_inserted_entries
=
0
;
while
(
psz_parse
&&
(
psz_parse
=
strcasestr
(
psz_parse
,
"<"
)
)
)
{
{
if
(
!
strncasecmp
(
psz_parse
,
"<!--"
,
4
)
)
/* Metadata Node */
{
if
(
!
strncasecmp
(
psz_node
,
"TITLE"
,
5
)
)
/* this is a comment */
ReadElement
(
p_xml_reader
,
&
psz_title
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"-->"
)
)
)
if
(
!
strncasecmp
(
psz_node
,
"AUTHOR"
,
6
)
)
psz_parse
+=
3
;
ReadElement
(
p_xml_reader
,
&
psz_artist
)
;
else
continue
;
if
(
!
strncasecmp
(
psz_node
,
"COPYRIGHT"
,
9
)
)
}
ReadElement
(
p_xml_reader
,
&
psz_copyright
);
else
if
(
!
strncasecmp
(
psz_parse
,
"<PARAM "
,
7
)
)
if
(
!
strncasecmp
(
psz_node
,
"MOREINFO"
,
8
)
)
{
{
bool
b_encoding_flag
=
false
;
do
psz_parse
=
SkipBlanks
(
psz_parse
+
7
,
(
unsigned
)
-
1
);
if
(
!
strncasecmp
(
psz_parse
,
"name"
,
4
)
)
{
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
psz_backup
=
++
psz_parse
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
i_strlen
=
psz_parse
-
psz_backup
;
if
(
i_strlen
<
1
)
continue
;
msg_Dbg
(
p_demux
,
"param name strlen: %d"
,
i_strlen
);
psz_string
=
xmalloc
(
i_strlen
+
1
);
memcpy
(
psz_string
,
psz_backup
,
i_strlen
);
psz_string
[
i_strlen
]
=
'\0'
;
msg_Dbg
(
p_demux
,
"param name: %s"
,
psz_string
);
b_encoding_flag
=
!
strcasecmp
(
psz_string
,
"encoding"
);
free
(
psz_string
);
}
else
continue
;
}
else
continue
;
}
psz_parse
++
;
if
(
!
strncasecmp
(
psz_parse
,
"value"
,
5
)
)
{
{
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
psz_txt
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
psz_node
);
{
psz_backup
=
++
psz_parse
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
i_strlen
=
psz_parse
-
psz_backup
;
if
(
i_strlen
<
1
)
continue
;
msg_Dbg
(
p_demux
,
"param value strlen: %d"
,
i_strlen
);
psz_string
=
xmalloc
(
i_strlen
+
1
);
memcpy
(
psz_string
,
psz_backup
,
i_strlen
);
psz_string
[
i_strlen
]
=
'\0'
;
msg_Dbg
(
p_demux
,
"param value: %s"
,
psz_string
);
if
(
b_encoding_flag
&&
!
strcasecmp
(
psz_string
,
"utf-8"
)
)
p_sys
->
b_utf8
=
true
;
free
(
psz_string
);
}
else
continue
;
}
else
continue
;
}
}
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"/>"
)
)
)
while
(
psz_txt
&&
strncasecmp
(
psz_txt
,
"HREF"
,
4
)
);
psz_parse
+=
2
;
else
continue
;
if
(
!
psz_txt
)
}
ReadElement
(
p_xml_reader
,
&
psz_moreinfo
);
else
if
(
!
strncasecmp
(
psz_parse
,
"<BANNER"
,
7
)
)
else
{
psz_moreinfo
=
strdup
(
psz_node
);
/* We skip this element */
resolve_xml_special_chars
(
psz_moreinfo
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"</BANNER>"
)
)
)
psz_parse
+=
9
;
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<PREVIEWDURATION"
,
16
)
||
!
strncasecmp
(
psz_parse
,
"<LOGURL"
,
7
)
||
!
strncasecmp
(
psz_parse
,
"<Skin"
,
5
)
)
{
/* We skip this element */
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"/>"
)
)
)
psz_parse
+=
2
;
else
continue
;
}
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<BASE "
,
6
)
)
if
(
!
strncasecmp
(
psz_node
,
"ABSTRACT"
,
8
)
)
ReadElement
(
p_xml_reader
,
&
psz_description
);
if
(
!
strncasecmp
(
psz_node
,
"DURATION"
,
8
)
)
i_duration
=
ParseTime
(
p_xml_reader
);
if
(
!
strncasecmp
(
psz_node
,
"STARTTIME"
,
9
)
)
i_start
=
ParseTime
(
p_xml_reader
);
/* Reference Node */
/* All ref node will be converted into an entry */
if
(
!
strncasecmp
(
psz_node
,
"REF"
,
3
)
)
{
{
psz_parse
=
SkipBlanks
(
psz_parse
+
6
,
(
unsigned
)
-
1
);
*
pi_n_entry
=
*
pi_n_entry
+
1
;
if
(
!
strncasecmp
(
psz_parse
,
"HREF"
,
4
)
)
if
(
!
psz_title
)
psz_title
=
input_item_GetTitle
(
p_current_input
);
if
(
!
psz_artist
)
psz_artist
=
input_item_GetArtist
(
p_current_input
);
if
(
!
psz_copyright
)
psz_copyright
=
input_item_GetCopyright
(
p_current_input
);
if
(
!
psz_description
)
psz_description
=
input_item_GetDescription
(
p_current_input
);
do
{
{
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
psz_txt
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
psz_node
);
{
psz_backup
=
++
psz_parse
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
StoreString
(
p_demux
,
(
b_entry
?
&
psz_base_entry
:
&
psz_base_asx
),
psz_backup
,
psz_parse
);
}
else
continue
;
}
else
continue
;
}
}
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"/>"
)
)
)
while
(
strncasecmp
(
psz_txt
,
"HREF"
,
4
)
);
psz_parse
+=
2
;
psz_href
=
strdup
(
psz_node
);
else
continue
;
}
if
(
asprintf
(
&
psz_name
,
"%d. %s"
,
*
pi_n_entry
,
psz_title
)
==
-
1
)
else
if
(
!
strncasecmp
(
psz_parse
,
"<TITLE>"
,
7
)
)
psz_name
=
strdup
(
psz_title
);
{
resolve_xml_special_chars
(
psz_href
);
psz_backup
=
psz_parse
+=
7
;
psz_mrl
=
ProcessMRL
(
psz_href
,
psz_prefix
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"</TITLE>"
)
)
)
/* Add Time information */
i_options
=
0
;
if
(
i_start
)
{
{
StoreString
(
p_demux
,
(
b_entry
?
&
psz_title_entry
:
&
psz_title_asx
),
psz_backup
,
psz_parse
);
if
(
asprintf
(
ppsz_options
,
":start-time=%d"
,(
int
)
i_start
/
1000000
)
!=
-
1
)
psz_parse
+=
8
;
i_options
++
;
}
}
else
continue
;
if
(
i_duration
)
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<Author>"
,
8
)
)
{
psz_backup
=
psz_parse
+=
8
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"</Author>"
)
)
)
{
{
StoreString
(
p_demux
,
(
b_entry
?
&
psz_artist_entry
:
&
psz_artist_asx
),
psz_backup
,
psz_parse
);
if
(
asprintf
(
ppsz_options
+
i_options
,
":stop-time=%d"
,
psz_parse
+=
9
;
(
int
)
(
i_start
+
i_duration
)
/
1000000
)
!=
-
1
)
i_options
++
;
}
}
else
continue
;
/* Create the input item */
p_entry
=
input_item_NewExt
(
psz_mrl
,
psz_name
,
i_options
,
(
const
char
*
const
*
)
ppsz_options
,
VLC_INPUT_OPTION_TRUSTED
,
i_duration
);
input_item_CopyOptions
(
p_current_input
,
p_entry
);
/* Add the metadata */
if
(
psz_name
)
input_item_SetTitle
(
p_entry
,
psz_name
);
if
(
psz_artist
)
input_item_SetArtist
(
p_entry
,
psz_artist
);
if
(
psz_copyright
)
input_item_SetCopyright
(
p_entry
,
psz_copyright
);
if
(
psz_moreinfo
)
input_item_SetURL
(
p_entry
,
psz_moreinfo
);
if
(
psz_description
)
input_item_SetDescription
(
p_entry
,
psz_description
);
if
(
i_duration
>
0
)
input_item_SetDuration
(
p_entry
,
i_duration
);
input_item_node_AppendItem
(
p_subitems
,
p_entry
);
while
(
i_options
)
free
(
ppsz_options
[
--
i_options
]
);
free
(
psz_name
);
free
(
psz_mrl
);
}
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<Copyright"
,
10
)
)
}
}
while
(
i_type
!=
XML_READER_ENDELEM
||
strncasecmp
(
psz_node
,
"ENTRY"
,
5
)
);
free
(
psz_href
);
free
(
psz_title
);
free
(
psz_artist
);
free
(
psz_copyright
);
free
(
psz_moreinfo
);
free
(
psz_description
);
}
static
int
Demux
(
demux_t
*
p_demux
)
{
const
char
*
psz_node
=
NULL
;
char
*
psz_txt
=
NULL
;
char
*
psz_base
=
FindPrefix
(
p_demux
);
char
*
psz_title_asx
=
NULL
;
char
*
psz_entryref
=
NULL
;
xml_reader_t
*
p_xml_reader
=
NULL
;
bool
b_first_node
=
false
;
int
i_type
;
int
i_n_entry
=
0
;
p_xml_reader
=
xml_ReaderCreate
(
p_demux
,
p_demux
->
s
);
if
(
!
p_xml_reader
)
{
msg_Err
(
p_demux
,
"Cannot parse ASX input file as XML"
);
goto
error
;
}
input_item_t
*
p_current_input
=
GetCurrentItem
(
p_demux
);
input_item_node_t
*
p_subitems
=
input_item_node_Create
(
p_current_input
);
do
{
i_type
=
xml_ReaderNextNode
(
p_xml_reader
,
&
psz_node
);
if
(
i_type
==
XML_READER_STARTELEM
)
{
if
(
!
b_first_node
)
{
{
psz_backup
=
psz_parse
+=
11
;
if
(
!
strncasecmp
(
psz_node
,
"ASX"
,
3
)
)
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"</Copyright>"
)
)
)
b_first_node
=
true
;
else
{
{
StoreString
(
p_demux
,
(
b_entry
?
&
psz_copyright_entry
:
&
psz_copyright_asx
),
psz_backup
,
psz_parse
);
msg_Err
(
p_demux
,
"invalid root node"
);
psz_parse
+=
12
;
goto
error
;
}
}
else
continue
;
}
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<MoreInfo "
,
10
)
)
/* Metadata Node Handler */
if
(
!
strncasecmp
(
psz_node
,
"TITLE"
,
5
)
)
{
{
psz_parse
=
SkipBlanks
(
psz_parse
+
10
,
(
unsigned
)
-
1
);
ReadElement
(
p_xml_reader
,
&
psz_title_asx
);
if
(
!
strncasecmp
(
psz_parse
,
"HREF"
,
4
)
)
input_item_SetTitle
(
p_current_input
,
psz_title_asx
);
{
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
psz_backup
=
++
psz_parse
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
StoreString
(
p_demux
,
(
b_entry
?
&
psz_moreinfo_entry
:
&
psz_moreinfo_asx
),
psz_backup
,
psz_parse
);
}
else
continue
;
}
else
continue
;
}
if
(
(
psz_backup
=
strcasestr
(
psz_parse
,
"/>"
)
)
)
psz_parse
=
psz_backup
+
2
;
else
if
(
(
psz_backup
=
strcasestr
(
psz_parse
,
"</MoreInfo>"
)
)
)
psz_parse
=
psz_backup
+
11
;
else
{
psz_parse
=
NULL
;
continue
;
}
}
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<ABSTRACT>"
,
10
)
)
if
(
!
strncasecmp
(
psz_node
,
"AUTHOR"
,
6
)
)
{
{
psz_backup
=
psz_parse
+=
10
;
ReadElement
(
p_xml_reader
,
&
psz_txt
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"</ABSTRACT>"
)
)
)
input_item_SetArtist
(
p_current_input
,
psz_txt
);
{
StoreString
(
p_demux
,
(
b_entry
?
&
psz_abstract_entry
:
&
psz_abstract_asx
),
psz_backup
,
psz_parse
);
psz_parse
+=
11
;
}
else
continue
;
}
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<EntryRef "
,
10
)
)
if
(
!
strncasecmp
(
psz_node
,
"COPYRIGHT"
,
9
)
)
{
{
psz_parse
=
SkipBlanks
(
psz_parse
+
10
,
(
unsigned
)
-
1
);
ReadElement
(
p_xml_reader
,
&
psz_txt
);
if
(
!
strncasecmp
(
psz_parse
,
"HREF"
,
4
)
)
input_item_SetCopyright
(
p_current_input
,
psz_txt
);
{
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
psz_backup
=
++
psz_parse
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
i_strlen
=
psz_parse
-
psz_backup
;
if
(
i_strlen
<
1
)
continue
;
psz_string
=
xmalloc
(
i_strlen
+
1
);
memcpy
(
psz_string
,
psz_backup
,
i_strlen
);
psz_string
[
i_strlen
]
=
'\0'
;
input_item_t
*
p_input
;
p_input
=
input_item_New
(
psz_string
,
psz_title_asx
);
input_item_CopyOptions
(
p_current_input
,
p_input
);
input_item_node_AppendItem
(
p_subitems
,
p_input
);
vlc_gc_decref
(
p_input
);
free
(
psz_string
);
}
else
continue
;
}
else
continue
;
}
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"/>"
)
)
)
psz_parse
+=
2
;
}
}
else
if
(
!
strncasecmp
(
psz_parse
,
"</Entry>
"
,
8
)
)
if
(
!
strncasecmp
(
psz_node
,
"MOREINFO
"
,
8
)
)
{
{
input_item_t
*
p_entry
=
NULL
;
const
char
*
psz_tmp
;
char
*
psz_name
=
NULL
;
do
char
*
ppsz_options
[
2
];
int
i_options
=
0
;
/* add a new entry */
psz_parse
+=
8
;
if
(
!
b_entry
)
{
{
msg_Err
(
p_demux
,
"end of entry without start?"
);
psz_tmp
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
psz_node
);
continue
;
}
}
while
(
psz_tmp
&&
strncasecmp
(
psz_tmp
,
"HREF"
,
4
)
);
if
(
!
psz_href
)
if
(
!
psz_tmp
)
// If HREF attribute doesn't exist
{
ReadElement
(
p_xml_reader
,
&
psz_txt
);
msg_Err
(
p_demux
,
"entry without href?"
);
continue
;
}
/* An skip entry is an ad only if other entries exist without skip */
if
(
p_sys
->
b_skip_ads
&&
b_skip_entry
&&
i_inserted_entries
!=
0
)
{
char
*
psz_current_input_name
=
input_item_GetName
(
p_current_input
);
msg_Dbg
(
p_demux
,
"skipped entry %d %s (%s)"
,
i_entry_count
,
(
psz_title_entry
?
psz_title_entry
:
psz_current_input_name
),
psz_href
);
free
(
psz_current_input_name
);
}
else
else
{
psz_txt
=
strdup
(
psz_node
);
if
(
i_starttime
||
i_duration
)
{
if
(
i_starttime
)
{
if
(
asprintf
(
ppsz_options
+
i_options
,
":start-time=%d"
,
i_starttime
)
==
-
1
)
*
(
ppsz_options
+
i_options
)
=
NULL
;
else
++
i_options
;
}
if
(
i_duration
)
{
if
(
asprintf
(
ppsz_options
+
i_options
,
":stop-time=%d"
,
i_starttime
+
i_duration
)
==
-
1
)
*
(
ppsz_options
+
i_options
)
=
NULL
;
else
++
i_options
;
}
}
/* create the new entry */
char
*
psz_current_input_name
=
input_item_GetName
(
p_current_input
);
if
(
asprintf
(
&
psz_name
,
"%d %s"
,
i_entry_count
,
(
psz_title_entry
?
psz_title_entry
:
psz_current_input_name
)
)
!=
-
1
)
{
char
*
psz_mrl
=
ProcessMRL
(
psz_href
,
p_demux
->
p_sys
->
psz_prefix
);
p_entry
=
input_item_NewExt
(
psz_mrl
,
psz_name
,
i_options
,
(
const
char
*
const
*
)
ppsz_options
,
VLC_INPUT_OPTION_TRUSTED
,
-
1
);
free
(
psz_name
);
free
(
psz_mrl
);
input_item_CopyOptions
(
p_current_input
,
p_entry
);
while
(
i_options
)
{
psz_name
=
ppsz_options
[
--
i_options
];
free
(
psz_name
);
}
psz_name
=
NULL
;
if
(
psz_title_entry
)
input_item_SetTitle
(
p_entry
,
psz_title_entry
);
if
(
psz_artist_entry
)
input_item_SetArtist
(
p_entry
,
psz_artist_entry
);
if
(
psz_copyright_entry
)
input_item_SetCopyright
(
p_entry
,
psz_copyright_entry
);
if
(
psz_moreinfo_entry
)
input_item_SetURL
(
p_entry
,
psz_moreinfo_entry
);
if
(
psz_abstract_entry
)
input_item_SetDescription
(
p_entry
,
psz_abstract_entry
);
i_inserted_entries
++
;
if
(
p_sys
->
b_skip_ads
&&
b_skip_entry
)
{
// We put the entry as a backup for unique ad case
uniq_entry_ad_backup
=
p_entry
;
}
else
{
if
(
uniq_entry_ad_backup
!=
NULL
)
{
vlc_gc_decref
(
uniq_entry_ad_backup
);
uniq_entry_ad_backup
=
NULL
;
}
input_item_node_AppendItem
(
p_subitems
,
p_entry
);
vlc_gc_decref
(
p_entry
);
}
}
free
(
psz_current_input_name
);
}
/* cleanup entry */
;
resolve_xml_special_chars
(
psz_txt
);
FREENULL
(
psz_href
);
input_item_SetURL
(
p_current_input
,
psz_txt
);
FREENULL
(
psz_title_entry
);
FREENULL
(
psz_base_entry
);
FREENULL
(
psz_artist_entry
);
FREENULL
(
psz_copyright_entry
);
FREENULL
(
psz_moreinfo_entry
);
FREENULL
(
psz_abstract_entry
);
b_entry
=
false
;
}
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<Entry"
,
6
)
)
if
(
!
strncasecmp
(
psz_node
,
"ABSTRACT"
,
8
)
)
{
{
char
*
psz_clientskip
;
ReadElement
(
p_xml_reader
,
&
psz_txt
);
psz_parse
+=
6
;
input_item_SetDescription
(
p_current_input
,
psz_txt
);
if
(
b_entry
)
{
msg_Err
(
p_demux
,
"We already are in an entry section"
);
continue
;
}
i_entry_count
+=
1
;
b_entry
=
true
;
psz_clientskip
=
strcasestr
(
psz_parse
,
"clientskip=
\"
no
\"
"
);
psz_parse
=
strcasestr
(
psz_parse
,
">"
);
/* If clientskip was enabled ... this is an ad */
b_skip_entry
=
(
NULL
!=
psz_clientskip
)
&&
(
psz_clientskip
<
psz_parse
);
// init entry details
FREENULL
(
psz_href
);
i_starttime
=
0
;
i_duration
=
0
;
}
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<Ref "
,
5
)
)
{
psz_parse
=
SkipBlanks
(
psz_parse
+
5
,
(
unsigned
)
-
1
);
if
(
!
b_entry
)
{
msg_Err
(
p_demux
,
"A ref outside an entry section"
);
continue
;
}
if
(
!
strncasecmp
(
psz_parse
,
"HREF"
,
4
)
)
/* Base Node handler */
{
if
(
!
strncasecmp
(
psz_node
,
"BASE"
,
4
)
)
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
ReadElement
(
p_xml_reader
,
&
psz_base
);
{
psz_backup
=
++
psz_parse
;
psz_backup
=
SkipBlanks
(
psz_backup
,
(
unsigned
)
-
1
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
char
*
psz_tmp
;
i_strlen
=
psz_parse
-
psz_backup
;
if
(
i_strlen
<
1
)
continue
;
if
(
psz_href
)
{
/* we have allready one href in this entry, lets make new input from it and
continue with new href, don't free meta/options*/
input_item_t
*
p_entry
=
NULL
;
char
*
psz_name
=
input_item_GetName
(
p_current_input
);
char
*
psz_mrl
=
ProcessMRL
(
psz_href
,
p_demux
->
p_sys
->
psz_prefix
);
p_entry
=
input_item_NewExt
(
psz_mrl
,
psz_name
,
0
,
NULL
,
VLC_INPUT_OPTION_TRUSTED
,
-
1
);
free
(
psz_mrl
);
input_item_CopyOptions
(
p_current_input
,
p_entry
);
if
(
psz_title_entry
)
input_item_SetTitle
(
p_entry
,
psz_title_entry
);
if
(
psz_artist_entry
)
input_item_SetArtist
(
p_entry
,
psz_artist_entry
);
if
(
psz_copyright_entry
)
input_item_SetCopyright
(
p_entry
,
psz_copyright_entry
);
if
(
psz_moreinfo_entry
)
input_item_SetURL
(
p_entry
,
psz_moreinfo_entry
);
if
(
psz_abstract_entry
)
input_item_SetDescription
(
p_entry
,
psz_abstract_entry
);
input_item_node_AppendItem
(
p_subitems
,
p_entry
);
vlc_gc_decref
(
p_entry
);
}
free
(
psz_href
);
psz_href
=
xmalloc
(
i_strlen
+
1
);
memcpy
(
psz_href
,
psz_backup
,
i_strlen
);
psz_href
[
i_strlen
]
=
'\0'
;
psz_tmp
=
psz_href
+
(
i_strlen
-
1
);
while
(
psz_tmp
>=
psz_href
&&
(
*
psz_tmp
==
'\r'
||
*
psz_tmp
==
'\n'
)
)
{
*
psz_tmp
=
'\0'
;
psz_tmp
++
;
}
}
else
continue
;
}
else
continue
;
}
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
">"
)
)
)
psz_parse
++
;
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<starttime "
,
11
)
)
{
psz_parse
=
SkipBlanks
(
psz_parse
+
11
,
(
unsigned
)
-
1
);
if
(
!
b_entry
)
{
msg_Err
(
p_demux
,
"starttime outside an entry section"
);
continue
;
}
if
(
!
strncasecmp
(
psz_parse
,
"value"
,
5
)
)
/* Entry Ref Handler */
{
if
(
!
strncasecmp
(
psz_node
,
"ENTRYREF"
,
7
)
)
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
psz_backup
=
++
psz_parse
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
i_strlen
=
psz_parse
-
psz_backup
;
if
(
i_strlen
<
1
)
continue
;
i_starttime
=
ParseTime
(
psz_backup
,
i_strlen
);
}
else
continue
;
}
else
continue
;
}
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
">"
)
)
)
psz_parse
++
;
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<duration "
,
11
)
)
{
{
psz_parse
=
SkipBlanks
(
psz_parse
+
5
,
(
unsigned
)
-
1
)
;
const
char
*
psz_tmp
;
if
(
!
b_entry
)
do
{
{
msg_Err
(
p_demux
,
"duration outside an entry section"
);
psz_tmp
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
psz_node
);
continue
;
}
}
while
(
psz_tmp
&&
!
strncasecmp
(
psz_tmp
,
"HREF"
,
4
)
);
if
(
!
strncasecmp
(
psz_parse
,
"value"
,
5
)
)
/* Create new input item */
{
input_item_t
*
p_input
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
psz_txt
=
strdup
(
psz_node
);
{
resolve_xml_special_chars
(
psz_txt
);
psz_backup
=
++
psz_parse
;
p_input
=
input_item_New
(
psz_txt
,
psz_title_asx
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
input_item_CopyOptions
(
p_current_input
,
p_input
);
{
input_item_node_AppendItem
(
p_subitems
,
p_input
);
i_strlen
=
psz_parse
-
psz_backup
;
if
(
i_strlen
<
1
)
continue
;
vlc_gc_decref
(
p_input
);
i_duration
=
ParseTime
(
psz_backup
,
i_strlen
);
}
else
continue
;
}
else
continue
;
}
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
">"
)
)
)
psz_parse
++
;
else
continue
;
}
}
else
if
(
!
strncasecmp
(
psz_parse
,
"</ASX"
,
5
)
)
/* Entry Handler */
if
(
!
strncasecmp
(
psz_node
,
"ENTRY"
,
5
)
)
{
{
if
(
psz_title_asx
)
input_item_SetTitle
(
p_current_input
,
psz_title_asx
);
ProcessEntry
(
&
i_n_entry
,
p_xml_reader
,
p_subitems
,
if
(
psz_artist_asx
)
input_item_SetArtist
(
p_current_input
,
psz_artist_asx
);
p_current_input
,
psz_base
);
if
(
psz_copyright_asx
)
input_item_SetCopyright
(
p_current_input
,
psz_copyright_asx
);
if
(
psz_moreinfo_asx
)
input_item_SetURL
(
p_current_input
,
psz_moreinfo_asx
);
if
(
psz_abstract_asx
)
input_item_SetDescription
(
p_current_input
,
psz_abstract_asx
);
FREENULL
(
psz_base_asx
);
FREENULL
(
psz_title_asx
);
FREENULL
(
psz_artist_asx
);
FREENULL
(
psz_copyright_asx
);
FREENULL
(
psz_moreinfo_asx
);
FREENULL
(
psz_abstract_asx
);
psz_parse
++
;
}
}
else
psz_parse
++
;
/* FIXME Unsupported elements
}
if
(
uniq_entry_ad_backup
!=
NULL
)
{
msg_Dbg
(
p_demux
,
"added unique entry even if ad"
);
/* If ASX contains a unique entry, we add it, it is probably not an ad */
input_item_node_AppendItem
(
p_subitems
,
uniq_entry_ad_backup
);
vlc_gc_decref
(
uniq_entry_ad_backup
);
}
#if 0
/* FIXME Unsupported elements */
PARAM
PARAM
EVENT
EVENT
REPEAT
REPEAT
ENDMARK
ENDMARK
STARTMARK
STARTMARK
#endif
*/
}
}
}
while
(
i_type
!=
XML_READER_ENDELEM
||
strncasecmp
(
psz_node
,
"ASX"
,
3
)
);
free
(
psz_base
);
free
(
psz_title_asx
);
free
(
psz_entryref
);
free
(
psz_txt
);
input_item_node_PostAndDelete
(
p_subitems
);
input_item_node_PostAndDelete
(
p_subitems
);
vlc_gc_decref
(
p_current_input
);
error:
if
(
p_xml_reader
)
xml_ReaderDelete
(
p_xml_reader
);
vlc_gc_decref
(
p_current_input
);
return
0
;
return
0
;
/* Needed for correct operation of go back */
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment