[vlc-commits] meta: xiph: parse embedded cuesheet
Francois Cartegnie
git at videolan.org
Sun Nov 22 17:46:34 CET 2015
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Sun Nov 22 14:40:27 2015 +0100| [df9ee5575f69f48988553d6fb924f97627377e9f] | committer: Francois Cartegnie
meta: xiph: parse embedded cuesheet
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=df9ee5575f69f48988553d6fb924f97627377e9f
---
modules/demux/xiph_metadata.c | 148 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 148 insertions(+)
diff --git a/modules/demux/xiph_metadata.c b/modules/demux/xiph_metadata.c
index 1fb9920..2e9ecba 100644
--- a/modules/demux/xiph_metadata.c
+++ b/modules/demux/xiph_metadata.c
@@ -159,6 +159,149 @@ static seekpoint_t * getChapterEntry( unsigned int i_index, chapters_array_t *p_
#define XIPHMETA_EncodedBy (1 << 11)
#define XIPHMETA_TrackTotal (1 << 12)
+static char * xiph_ExtractCueSheetMeta( const char *psz_line,
+ const char *psz_tag, int i_tag,
+ bool b_quoted )
+{
+ if( !strncasecmp( psz_line, psz_tag, i_tag ) )
+ {
+ if( !b_quoted )
+ return strdup( &psz_line[i_tag] );
+
+ /* Unquote string value */
+ char *psz_value = malloc( strlen( psz_line ) - i_tag + 1 );
+ if( psz_value )
+ {
+ char *psz_out = psz_value;
+ psz_line += i_tag;
+ bool b_escaped = false;
+ while( *psz_line )
+ {
+ switch( *psz_line )
+ {
+ case '\\':
+ if( b_escaped )
+ {
+ b_escaped = false;
+ *(psz_out++) = *psz_line;
+ }
+ else
+ {
+ b_escaped = true;
+ }
+ break;
+ case '"':
+ if( b_escaped )
+ {
+ b_escaped = false;
+ *(psz_out++) = *psz_line;
+ }
+ break;
+ default:
+ *(psz_out++) = *psz_line;
+ break;
+ }
+ psz_line++;
+ }
+ *psz_out = 0;
+ return psz_value;
+ }
+ }
+ return NULL;
+}
+
+static void xiph_ParseCueSheetMeta( unsigned *pi_flags, vlc_meta_t *p_meta,
+ const char *psz_line,
+ int *pi_seekpoint, seekpoint_t ***ppp_seekpoint,
+ seekpoint_t **pp_tmppoint, bool *pb_valid )
+{
+ VLC_UNUSED(pi_seekpoint);
+ VLC_UNUSED(ppp_seekpoint);
+
+ seekpoint_t *p_seekpoint = *pp_tmppoint;
+ char *psz_string;
+
+#define TRY_EXTRACT_CUEMETA(var, string, quoted) \
+ if( !(*pi_flags & XIPHMETA_##var) &&\
+ ( psz_string = xiph_ExtractCueSheetMeta( psz_line, string, sizeof(string) - 1, quoted ) ) )\
+ {\
+ vlc_meta_Set( p_meta, vlc_meta_##var, psz_string );\
+ free( psz_string );\
+ *pi_flags |= XIPHMETA_##var;\
+ }
+
+ TRY_EXTRACT_CUEMETA(Title, "TITLE \"", true)
+ else TRY_EXTRACT_CUEMETA(Genre, "REM GENRE ", false)
+ else TRY_EXTRACT_CUEMETA(Date, "REM DATE ", false)
+ else TRY_EXTRACT_CUEMETA(Artist, "PERFORMER \"", true)
+ else if( !strncasecmp( psz_line, " TRACK ", 8 ) )
+ {
+ if( p_seekpoint )
+ {
+ if( *pb_valid )
+ TAB_APPEND( *pi_seekpoint, *ppp_seekpoint, p_seekpoint );
+ else
+ vlc_seekpoint_Delete( p_seekpoint );
+ *pb_valid = false;
+ }
+ *pp_tmppoint = p_seekpoint = vlc_seekpoint_New();
+ }
+ else if( p_seekpoint && !strncasecmp( psz_line, " INDEX 01 ", 13 ) )
+ {
+ unsigned m, s, f;
+ if( sscanf( &psz_line[13], "%u:%u:%u", &m, &s, &f ) == 3 )
+ {
+ p_seekpoint->i_time_offset = CLOCK_FREQ * (m * 60 + s) + f * CLOCK_FREQ/75;
+ *pb_valid = true;
+ }
+ }
+ else if( p_seekpoint && !p_seekpoint->psz_name )
+ {
+ p_seekpoint->psz_name = xiph_ExtractCueSheetMeta( psz_line, " TITLE \"", 11, true );
+ }
+}
+
+static void xiph_ParseCueSheet( unsigned *pi_flags, vlc_meta_t *p_meta,
+ const char *p_data, int i_data,
+ int *pi_seekpoint, seekpoint_t ***ppp_seekpoint )
+{
+ seekpoint_t *p_seekpoint = NULL;
+ bool b_valid = false;
+
+ const char *p_head = p_data;
+ const char *p_tail = p_head;
+ while( p_tail < p_data + i_data )
+ {
+ if( *p_tail == 0x0D )
+ {
+ char *psz = strndup( p_head, p_tail - p_head );
+ if( psz )
+ {
+ xiph_ParseCueSheetMeta( pi_flags, p_meta, psz,
+ pi_seekpoint, ppp_seekpoint,
+ &p_seekpoint, &b_valid );
+ free( psz );
+ }
+ if( *(++p_tail) == 0x0A )
+ p_tail++;
+ p_head = p_tail;
+ }
+ else
+ {
+ p_tail++;
+ }
+ }
+
+
+ if( p_seekpoint )
+ {
+ if( b_valid )
+ TAB_APPEND( *pi_seekpoint, *ppp_seekpoint, p_seekpoint );
+ else
+ vlc_seekpoint_Delete( p_seekpoint );
+ }
+}
+
void vorbis_ParseComment( es_format_t *p_fmt, vlc_meta_t **pp_meta,
const uint8_t *p_data, int i_data,
int *i_attachments, input_attachment_t ***attachments,
@@ -357,6 +500,11 @@ void vorbis_ParseComment( es_format_t *p_fmt, vlc_meta_t **pp_meta,
}
}
}
+ else if( !strncasecmp(psz_comment, "cuesheet=", 9) )
+ {
+ xiph_ParseCueSheet( &hasMetaFlags, p_meta, &psz_comment[9], n - 9,
+ i_seekpoint, ppp_seekpoint );
+ }
else if( strchr( psz_comment, '=' ) )
{
/* generic (PERFORMER/LICENSE/ORGANIZATION/LOCATION/CONTACT/ISRC,
More information about the vlc-commits
mailing list