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
a6628c50
Commit
a6628c50
authored
Apr 10, 2015
by
Jean-Baptiste Kempf
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Rewrites asx file support using vlc_xml API"
This reverts commit
4c0b7973
. Ref #14062
parent
270c2b19
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
630 additions
and
297 deletions
+630
-297
modules/demux/playlist/asx.c
modules/demux/playlist/asx.c
+630
-297
No files found.
modules/demux/playlist/asx.c
View file @
a6628c50
/*****************************************************************************
/*****************************************************************************
* asx.c : ASX playlist format import
* asx.c : ASX playlist format import
*****************************************************************************
*****************************************************************************
* Copyright (C) 2005-20
13
VLC authors and VideoLAN
* Copyright (C) 2005-20
06
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,8 +21,7 @@
...
@@ -21,8 +21,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
*****************************************************************************/
/* See also:
/* See also: http://msdn.microsoft.com/library/en-us/wmplay10/mmp_sdk/windowsmediametafilereference.asp
* http://msdn.microsoft.com/en-us/library/windows/desktop/dd564668.aspx
*/
*/
/*****************************************************************************
/*****************************************************************************
...
@@ -34,15 +33,19 @@
...
@@ -34,15 +33,19 @@
#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
;
};
};
/*****************************************************************************
/*****************************************************************************
...
@@ -50,391 +53,721 @@ struct demux_sys_t
...
@@ -50,391 +53,721 @@ struct demux_sys_t
*****************************************************************************/
*****************************************************************************/
static
int
Demux
(
demux_t
*
p_demux
);
static
int
Demux
(
demux_t
*
p_demux
);
static
mtime_t
ParseTime
(
xml_reader_t
*
p_xml_reader
)
static
int
StoreString
(
demux_t
*
p_demux
,
char
**
ppsz_string
,
const
char
*
psz_source_start
,
const
char
*
psz_source_end
)
{
{
char
*
psz_value
=
NULL
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
char
*
psz_start
=
NULL
;
unsigned
len
=
psz_source_end
-
psz_source_start
;
const
char
*
psz_node
=
NULL
;
const
char
*
psz_txt
=
NULL
;
int
i_subfractions
=
-
1
;
free
(
*
ppsz_string
)
;
int
i_subresult
=
0
;
char
*
buf
=
*
ppsz_string
=
malloc
((
len
*
(
1
+
!
p_sys
->
b_utf8
))
+
1
);
mtime_t
i_result
=
0
;
if
(
buf
==
NULL
)
return
VLC_ENOMEM
;
do
if
(
p_sys
->
b_utf8
)
{
{
psz_txt
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
psz_node
);
memcpy
(
buf
,
psz_source_start
,
len
);
(
*
ppsz_string
)[
len
]
=
'\0'
;
EnsureUTF8
(
*
ppsz_string
);
}
}
while
(
psz_txt
&&
strncasecmp
(
psz_txt
,
"VALUE"
,
5
)
);
else
psz_value
=
strdup
(
psz_node
);
psz_start
=
psz_value
;
while
(
*
psz_value
)
{
{
if
(
isdigit
(
*
psz_value
)
)
/* Latin-1 -> UTF-8 */
for
(
unsigned
i
=
0
;
i
<
len
;
i
++
)
{
{
i_subresult
=
i_subresult
*
10
;
unsigned
char
c
=
psz_source_start
[
i
];
i_subresult
+=
*
psz_value
-
'0'
;
if
(
c
&
0x80
)
if
(
i_subfractions
!=
-
1
)
i_subfractions
++
;
}
else
if
(
*
psz_value
==
':'
)
{
{
i_result
+=
i_subresult
;
*
buf
++
=
0xc0
|
(
c
>>
6
);
i_result
=
i_result
*
60
;
*
buf
++
=
0x80
|
(
c
&
0x3f
);
i_subresult
=
0
;
}
}
else
if
(
*
psz_value
==
'.'
)
else
{
*
buf
++
=
c
;
i_subfractions
=
0
;
i_result
+=
i_subresult
;
i_subresult
=
0
;
}
}
psz_value
++
;
*
buf
++
=
'\0'
;
buf
=
realloc
(
*
ppsz_string
,
buf
-
*
ppsz_string
);
if
(
buf
)
*
ppsz_string
=
buf
;
}
}
if
(
i_subfractions
==
-
1
)
return
VLC_SUCCESS
;
i_result
+=
i_subresult
;
}
/* Convert to microseconds */
static
char
*
SkipBlanks
(
char
*
s
,
size_t
i_strlen
)
if
(
i_subfractions
==
-
1
)
{
i_subfractions
=
0
;
while
(
i_strlen
>
0
)
{
while
(
i_subfractions
<
6
)
switch
(
*
s
)
{
{
i_subresult
=
i_subresult
*
10
;
case
' '
:
i_subfractions
++
;
case
'\t'
:
case
'\r'
:
case
'\n'
:
--
i_strlen
;
++
s
;
break
;
default:
i_strlen
=
0
;
}
}
i_result
=
i_result
*
1000000
;
}
if
(
i_subfractions
!=
-
1
)
return
s
;
i_result
+=
i_subresult
;
free
(
psz_start
);
return
i_result
;
}
}
static
void
ReadElement
(
xml_reader_t
*
p_xml_reader
,
char
**
ppsz_txt
)
static
int
ParseTime
(
char
*
s
,
size_t
i_strlen
)
{
{
const
char
*
psz_node
=
NULL
;
// need to parse hour:minutes:sec.fraction string
int
result
=
0
;
/* Read the text node */
int
val
;
xml_ReaderNextNode
(
p_xml_reader
,
&
psz_node
);
const
char
*
end
=
s
+
i_strlen
;
free
(
*
ppsz_txt
);
// skip leading spaces if any
*
ppsz_txt
=
strdup
(
psz_node
);
s
=
SkipBlanks
(
s
,
i_strlen
);
resolve_xml_special_chars
(
*
ppsz_txt
);
val
=
0
;
/* Read the end element */
while
(
(
s
<
end
)
&&
isdigit
((
unsigned
char
)
*
s
)
)
xml_ReaderNextNode
(
p_xml_reader
,
&
psz_node
);
{
/* TODO :
int
newval
=
val
*
10
+
(
*
s
-
'0'
);
* Currently we don't check the agreement of start and end element
if
(
newval
<
val
)
* This function is only used to read the element that cannot have child
{
* according to the reference.
// overflow
*/
val
=
0
;
break
;
}
val
=
newval
;
++
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'
);
if
(
newval
<
val
)
{
// overflow
val
=
0
;
break
;
}
val
=
newval
;
++
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'
);
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
}
}
return
result
;
}
}
/*****************************************************************************
/*****************************************************************************
* 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
(
demux_IsPathExtension
(
p_demux
,
".asx"
)
||
if
(
POKE
(
p_peek
,
"<asx"
,
4
)
||
demux_IsPathExtension
(
p_demux
,
".asx"
)
||
demux_IsPathExtension
(
p_demux
,
".wax"
)
||
demux_IsPathExtension
(
p_demux
,
".wax"
)
||
demux_IsPathExtension
(
p_demux
,
".wvx"
)
||
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
void
ProcessEntry
(
int
*
pi_n_entry
,
xml_reader_t
*
p_xml_reader
,
static
int
Demux
(
demux_t
*
p_demux
)
input_item_node_t
*
p_subitems
,
input_item_t
*
p_current_input
,
char
*
psz_prefix
)
{
{
const
char
*
psz_node
=
NULL
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
const
char
*
psz_txt
=
NULL
;
char
*
psz_parse
=
NULL
;
int
i_type
;
char
*
psz_backup
=
NULL
;
bool
b_entry
=
false
;
char
*
psz_title
=
NULL
;
input_item_t
*
p_current_input
=
GetCurrentItem
(
p_demux
);
char
*
psz_artist
=
NULL
;
char
*
psz_copyright
=
NULL
;
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
;
/* init txt */
if
(
p_sys
->
i_data_len
<
0
)
{
int64_t
i_pos
=
0
;
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
);
int
i_options
;
/* load the complete file */
mtime_t
i_start
=
0
;
for
(
;;
)
mtime_t
i_duration
=
0
;
{
char
*
ppsz_options
[
2
];
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
);
do
psz_parse
=
p_sys
->
psz_data
;
/* Find first element */
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"<ASX"
)
)
)
{
{
i_type
=
xml_ReaderNextNode
(
p_xml_reader
,
&
psz_node
);
/* ASX element */
char
*
psz_string
=
NULL
;
int
i_strlen
=
0
;
if
(
i_type
==
XML_READER_STARTELEM
)
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 */
/* this is a comment */
if
(
!
strncasecmp
(
psz_node
,
"TITLE"
,
5
)
)
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"-->"
)
)
)
ReadElement
(
p_xml_reader
,
&
psz_title
);
psz_parse
+=
3
;
if
(
!
strncasecmp
(
psz_node
,
"AUTHOR"
,
6
)
)
else
continue
;
ReadElement
(
p_xml_reader
,
&
psz_artist
);
}
if
(
!
strncasecmp
(
psz_node
,
"COPYRIGHT"
,
9
)
)
else
if
(
!
strncasecmp
(
psz_parse
,
"<PARAM "
,
7
)
)
ReadElement
(
p_xml_reader
,
&
psz_copyright
);
{
if
(
!
strncasecmp
(
psz_node
,
"MOREINFO"
,
8
)
)
bool
b_encoding_flag
=
false
;
psz_parse
=
SkipBlanks
(
psz_parse
+
7
,
(
unsigned
)
-
1
);
if
(
!
strncasecmp
(
psz_parse
,
"name"
,
4
)
)
{
{
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
,
"
\"
"
)
)
)
{
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
);
}
}
while
(
psz_txt
&&
strncasecmp
(
psz_txt
,
"HREF"
,
4
)
);
else
continue
;
}
if
(
!
psz_txt
)
else
continue
;
ReadElement
(
p_xml_reader
,
&
psz_moreinfo
);
}
psz_parse
++
;
if
(
!
strncasecmp
(
psz_parse
,
"value"
,
5
)
)
{
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 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
,
"/>"
)
)
)
psz_parse
+=
2
;
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<BANNER"
,
7
)
)
{
/* We skip this element */
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
)
)
{
psz_parse
=
SkipBlanks
(
psz_parse
+
6
,
(
unsigned
)
-
1
);
if
(
!
strncasecmp
(
psz_parse
,
"HREF"
,
4
)
)
{
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
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
,
"/>"
)
)
)
psz_parse
+=
2
;
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<TITLE>"
,
7
)
)
{
psz_backup
=
psz_parse
+=
7
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"</TITLE>"
)
)
)
{
StoreString
(
p_demux
,
(
b_entry
?
&
psz_title_entry
:
&
psz_title_asx
),
psz_backup
,
psz_parse
);
psz_parse
+=
8
;
}
else
continue
;
}
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
);
psz_parse
+=
9
;
}
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<Copyright"
,
10
)
)
{
psz_backup
=
psz_parse
+=
11
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"</Copyright>"
)
)
)
{
StoreString
(
p_demux
,
(
b_entry
?
&
psz_copyright_entry
:
&
psz_copyright_asx
),
psz_backup
,
psz_parse
);
psz_parse
+=
12
;
}
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<MoreInfo "
,
10
)
)
{
psz_parse
=
SkipBlanks
(
psz_parse
+
10
,
(
unsigned
)
-
1
);
if
(
!
strncasecmp
(
psz_parse
,
"HREF"
,
4
)
)
{
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
else
psz_moreinfo
=
strdup
(
psz_node
);
{
resolve_xml_special_chars
(
psz_moreinfo
);
psz_parse
=
NULL
;
continue
;
}
}
if
(
!
strncasecmp
(
psz_node
,
"ABSTRACT"
,
8
)
)
}
ReadElement
(
p_xml_reader
,
&
psz_description
);
else
if
(
!
strncasecmp
(
psz_parse
,
"<ABSTRACT>"
,
10
)
)
if
(
!
strncasecmp
(
psz_node
,
"DURATION"
,
8
)
)
{
i_duration
=
ParseTime
(
p_xml_reader
);
psz_backup
=
psz_parse
+=
10
;
if
(
!
strncasecmp
(
psz_node
,
"STARTTIME"
,
9
)
)
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"</ABSTRACT>"
)
)
)
i_start
=
ParseTime
(
p_xml_reader
);
{
StoreString
(
p_demux
,
(
b_entry
?
&
psz_abstract_entry
:
&
psz_abstract_asx
),
psz_backup
,
psz_parse
);
/* Reference Node */
psz_parse
+=
11
;
/* All ref node will be converted into an entry */
}
if
(
!
strncasecmp
(
psz_node
,
"REF"
,
3
)
)
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<EntryRef "
,
10
)
)
{
psz_parse
=
SkipBlanks
(
psz_parse
+
10
,
(
unsigned
)
-
1
);
if
(
!
strncasecmp
(
psz_parse
,
"HREF"
,
4
)
)
{
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
{
*
pi_n_entry
=
*
pi_n_entry
+
1
;
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
)
)
{
input_item_t
*
p_entry
=
NULL
;
char
*
psz_name
=
NULL
;
if
(
!
psz_title
)
char
*
ppsz_options
[
2
];
psz_title
=
input_item_GetTitle
(
p_current_input
);
int
i_options
=
0
;
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
/* add a new entry */
psz_parse
+=
8
;
if
(
!
b_entry
)
{
{
psz_txt
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
psz_node
);
msg_Err
(
p_demux
,
"end of entry without start?"
);
continue
;
}
}
while
(
strncasecmp
(
psz_txt
,
"HREF"
,
4
)
);
psz_href
=
strdup
(
psz_node
);
if
(
asprintf
(
&
psz_name
,
"%d. %s"
,
*
pi_n_entry
,
psz_title
)
==
-
1
)
psz_name
=
strdup
(
psz_title
);
resolve_xml_special_chars
(
psz_href
);
psz_mrl
=
ProcessMRL
(
psz_href
,
psz_prefix
);
/* Add Time information */
if
(
!
psz_href
)
i_options
=
0
;
if
(
i_start
)
{
{
if
(
asprintf
(
ppsz_options
,
":start-time=%d"
,(
int
)
i_start
/
1000000
)
!=
-
1
)
msg_Err
(
p_demux
,
"entry without href?"
);
i_options
++
;
continue
;
}
}
if
(
i_duration
)
/* 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
)
{
{
if
(
asprintf
(
ppsz_options
+
i_options
,
":stop-time=%d"
,
char
*
psz_current_input_name
=
input_item_GetName
(
p_current_input
);
(
int
)
(
i_start
+
i_duration
)
/
1000000
)
!=
-
1
)
msg_Dbg
(
p_demux
,
"skipped entry %d %s (%s)"
,
i_options
++
;
i_entry_count
,
(
psz_title_entry
?
psz_title_entry
:
psz_current_input_name
),
psz_href
);
free
(
psz_current_input_name
);
}
else
{
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 input item */
/* create the new entry */
p_entry
=
input_item_NewExt
(
psz_mrl
,
psz_name
,
i_options
,
char
*
psz_current_input_name
=
input_item_GetName
(
p_current_input
);
(
const
char
*
const
*
)
ppsz_options
,
VLC_INPUT_OPTION_TRUSTED
,
i_duration
);
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
);
input_item_CopyOptions
(
p_current_input
,
p_entry
);
while
(
i_options
)
{
psz_name
=
ppsz_options
[
--
i_options
];
free
(
psz_name
);
}
psz_name
=
NULL
;
/* Add the metadata */
if
(
psz_title_entry
)
input_item_SetTitle
(
p_entry
,
psz_title_entry
);
if
(
psz_name
)
if
(
psz_artist_entry
)
input_item_SetArtist
(
p_entry
,
psz_artist_entry
);
input_item_SetTitle
(
p_entry
,
psz_name
);
if
(
psz_copyright_entry
)
input_item_SetCopyright
(
p_entry
,
psz_copyright_entry
);
if
(
psz_artist
)
if
(
psz_moreinfo_entry
)
input_item_SetURL
(
p_entry
,
psz_moreinfo_entry
);
input_item_SetArtist
(
p_entry
,
psz_artist
);
if
(
psz_abstract_entry
)
input_item_SetDescription
(
p_entry
,
psz_abstract_entry
);
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
);
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
);
input_item_node_AppendItem
(
p_subitems
,
p_entry
);
vlc_gc_decref
(
p_entry
);
while
(
i_options
)
free
(
ppsz_options
[
--
i_options
]
);
free
(
psz_name
);
free
(
psz_mrl
);
}
}
}
}
free
(
psz_current_input_name
);
}
}
while
(
i_type
!=
XML_READER_ENDELEM
||
strncasecmp
(
psz_node
,
"ENTRY"
,
5
)
);
free
(
psz_href
);
/* cleanup entry */
;
free
(
psz_title
);
FREENULL
(
psz_href
);
free
(
psz_artist
);
FREENULL
(
psz_title_entry
);
free
(
psz_copyright
);
FREENULL
(
psz_base_entry
);
free
(
psz_moreinfo
);
FREENULL
(
psz_artist_entry
);
free
(
psz_description
);
FREENULL
(
psz_copyright_entry
);
}
FREENULL
(
psz_moreinfo_entry
);
FREENULL
(
psz_abstract_entry
);
static
int
Demux
(
demux_t
*
p_demux
)
b_entry
=
false
;
{
}
const
char
*
psz_node
=
NULL
;
else
if
(
!
strncasecmp
(
psz_parse
,
"<Entry"
,
6
)
)
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"
);
char
*
psz_clientskip
;
goto
error
;
psz_parse
+=
6
;
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
;
}
}
input_item_t
*
p_current_input
=
GetCurrentItem
(
p_demux
);
if
(
!
strncasecmp
(
psz_parse
,
"HREF"
,
4
)
)
input_item_node_t
*
p_subitems
=
input_item_node_Create
(
p_current_input
);
do
{
{
i_type
=
xml_ReaderNextNode
(
p_xml_reader
,
&
psz_node
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
if
(
i_type
==
XML_READER_STARTELEM
)
{
{
if
(
!
b_first_node
)
psz_backup
=
++
psz_parse
;
psz_backup
=
SkipBlanks
(
psz_backup
,
(
unsigned
)
-
1
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
{
if
(
!
strncasecmp
(
psz_node
,
"ASX"
,
3
)
)
char
*
psz_tmp
;
b_first_node
=
true
;
i_strlen
=
psz_parse
-
psz_backup
;
else
if
(
i_strlen
<
1
)
continue
;
if
(
psz_href
)
{
{
msg_Err
(
p_demux
,
"invalid root node"
);
/* we have allready one href in this entry, lets make new input from it and
goto
error
;
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
);
}
}
/* Metadata Node Handler */
free
(
psz_href
);
if
(
!
strncasecmp
(
psz_node
,
"TITLE"
,
5
)
)
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'
)
)
{
{
ReadElement
(
p_xml_reader
,
&
psz_title_asx
)
;
*
psz_tmp
=
'\0'
;
input_item_SetTitle
(
p_current_input
,
psz_title_asx
)
;
psz_tmp
++
;
}
}
if
(
!
strncasecmp
(
psz_node
,
"AUTHOR"
,
6
)
)
{
ReadElement
(
p_xml_reader
,
&
psz_txt
);
input_item_SetArtist
(
p_current_input
,
psz_txt
);
}
}
if
(
!
strncasecmp
(
psz_node
,
"COPYRIGHT"
,
9
)
)
else
continue
;
{
}
ReadElement
(
p_xml_reader
,
&
psz_txt
);
else
continue
;
input_item_SetCopyright
(
p_current_input
,
psz_txt
);
}
}
if
(
!
strncasecmp
(
psz_node
,
"MOREINFO"
,
8
)
)
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
">"
)
)
)
psz_parse
++
;
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"<starttime "
,
11
)
)
{
{
const
char
*
psz_tmp
;
psz_parse
=
SkipBlanks
(
psz_parse
+
11
,
(
unsigned
)
-
1
)
;
do
if
(
!
b_entry
)
{
{
psz_tmp
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
psz_node
);
msg_Err
(
p_demux
,
"starttime outside an entry section"
);
continue
;
}
}
while
(
psz_tmp
&&
strncasecmp
(
psz_tmp
,
"HREF"
,
4
)
);
if
(
!
psz_tmp
)
// If HREF attribute doesn't exist
if
(
!
strncasecmp
(
psz_parse
,
"value"
,
5
)
)
ReadElement
(
p_xml_reader
,
&
psz_txt
);
{
else
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
psz_txt
=
strdup
(
psz_node
);
{
psz_backup
=
++
psz_parse
;
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
{
i_strlen
=
psz_parse
-
psz_backup
;
if
(
i_strlen
<
1
)
continue
;
resolve_xml_special_chars
(
psz_txt
);
i_starttime
=
ParseTime
(
psz_backup
,
i_strlen
);
input_item_SetURL
(
p_current_input
,
psz_txt
);
}
}
if
(
!
strncasecmp
(
psz_node
,
"ABSTRACT"
,
8
)
)
else
continue
;
{
ReadElement
(
p_xml_reader
,
&
psz_txt
);
input_item_SetDescription
(
p_current_input
,
psz_txt
);
}
}
else
continue
;
/* Base Node handler */
}
if
(
!
strncasecmp
(
psz_node
,
"BASE"
,
4
)
)
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
">"
)
)
)
ReadElement
(
p_xml_reader
,
&
psz_base
)
;
psz_parse
++
;
else
continue
;
/* Entry Ref Handler */
}
if
(
!
strncasecmp
(
psz_node
,
"ENTRYREF"
,
7
)
)
else
if
(
!
strncasecmp
(
psz_parse
,
"<duration "
,
11
)
)
{
{
const
char
*
psz_tmp
;
psz_parse
=
SkipBlanks
(
psz_parse
+
5
,
(
unsigned
)
-
1
)
;
do
if
(
!
b_entry
)
{
{
psz_tmp
=
xml_ReaderNextAttr
(
p_xml_reader
,
&
psz_node
);
msg_Err
(
p_demux
,
"duration outside an entry section"
);
continue
;
}
}
while
(
psz_tmp
&&
!
strncasecmp
(
psz_tmp
,
"HREF"
,
4
)
);
/* Create new input item */
if
(
!
strncasecmp
(
psz_parse
,
"value"
,
5
)
)
input_item_t
*
p_input
;
{
psz_txt
=
strdup
(
psz_node
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
resolve_xml_special_chars
(
psz_txt
);
{
p_input
=
input_item_New
(
psz_txt
,
psz_title_asx
);
psz_backup
=
++
psz_parse
;
input_item_CopyOptions
(
p_current_input
,
p_input
);
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
"
\"
"
)
)
)
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
;
/* Entry Handler */
}
if
(
!
strncasecmp
(
psz_node
,
"ENTRY"
,
5
)
)
else
continue
;
}
if
(
(
psz_parse
=
strcasestr
(
psz_parse
,
">"
)
)
)
psz_parse
++
;
else
continue
;
}
else
if
(
!
strncasecmp
(
psz_parse
,
"</ASX"
,
5
)
)
{
{
ProcessEntry
(
&
i_n_entry
,
p_xml_reader
,
p_subitems
,
if
(
psz_title_asx
)
input_item_SetTitle
(
p_current_input
,
psz_title_asx
);
p_current_input
,
psz_base
);
if
(
psz_artist_asx
)
input_item_SetArtist
(
p_current_input
,
psz_artist_asx
);
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
);
return
0
;
vlc_gc_decref
(
p_current_input
);
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