[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