[vlc-devel] [PATCH] vlc_meta: allow multiple metas

Francois Cartegnie fcvlcdev at free.fr
Sat Aug 9 12:11:59 CEST 2014


Proposal.
We need more than just one entry for some meta types.
(Director, Astist, ...)

* I'm not fan of const char * returns we have with Get for now and the
Extra API does copy everything. I might change GetList to copies as well.

* I've set an arbitrary limit of 255 entries per meta. Do we need a limit ?

* Should we reject multiples entries for some meta ? (ie: does multiple now
playing makes sense ?)

Francois

---
 include/vlc_meta.h |  3 ++
 src/input/meta.c   | 96 +++++++++++++++++++++++++++++++++++++++++++++++-------
 src/libvlccore.sym |  2 ++
 3 files changed, 90 insertions(+), 11 deletions(-)

diff --git a/include/vlc_meta.h b/include/vlc_meta.h
index c3bf801..e0b5496 100644
--- a/include/vlc_meta.h
+++ b/include/vlc_meta.h
@@ -71,8 +71,11 @@ struct vlc_meta_t;
 
 VLC_API vlc_meta_t * vlc_meta_New( void ) VLC_USED;
 VLC_API void vlc_meta_Delete( vlc_meta_t *m );
+VLC_API void vlc_meta_Add( vlc_meta_t *p_meta, vlc_meta_type_t meta_type, const char *psz_val );
 VLC_API void vlc_meta_Set( vlc_meta_t *p_meta, vlc_meta_type_t meta_type, const char *psz_val );
 VLC_API const char * vlc_meta_Get( const vlc_meta_t *p_meta, vlc_meta_type_t meta_type );
+VLC_API const char ** vlc_meta_GetList( const vlc_meta_t *p_meta, vlc_meta_type_t meta_type,
+                                        size_t * pi_nb );
 
 VLC_API void vlc_meta_AddExtra( vlc_meta_t *m, const char *psz_name, const char *psz_value );
 VLC_API const char * vlc_meta_GetExtra( const vlc_meta_t *m, const char *psz_name );
diff --git a/src/input/meta.c b/src/input/meta.c
index 892b4af..493d466 100644
--- a/src/input/meta.c
+++ b/src/input/meta.c
@@ -38,9 +38,18 @@
 #include "input_internal.h"
 #include "../playlist/art.h"
 
+typedef struct vlc_meta_values_t vlc_meta_values_t;
+
+struct vlc_meta_values_t
+{
+    char  **ppsz_values;
+    uint8_t i_size; /* allocated size */
+    uint8_t i_count;/* number of values */
+};
+
 struct vlc_meta_t
 {
-    char * ppsz_meta[VLC_META_TYPE_COUNT];
+    vlc_meta_values_t rg_metavals[VLC_META_TYPE_COUNT];
 
     vlc_dictionary_t extra_tags;
 
@@ -81,6 +90,50 @@ const char * vlc_meta_TypeToLocalizedString( vlc_meta_type_t meta_type )
     return vlc_gettext (posix_names[meta_type]);
 };
 
+/**
+ * vlc_meta_values helpers.
+ * Manages the multi-valued meta arrays
+ */
+
+static void vlc_meta_values_add( vlc_meta_values_t *p_metavalues, const char *psz_val )
+{
+    if ( p_metavalues->i_count == UINT8_MAX )
+        return;
+
+    /* resize our storage if needed */
+    if ( p_metavalues->i_count == p_metavalues->i_size )
+    {
+        uint8_t i_newsize = VLC_CLIP( (uint16_t)p_metavalues->i_size * 2, 1, UINT8_MAX );
+        char **ppsz_values_new = realloc( p_metavalues->ppsz_values, i_newsize );
+        if ( ppsz_values_new ) /* realloc can fail */
+        {
+            p_metavalues->ppsz_values = ppsz_values_new;
+            p_metavalues->i_size = i_newsize;
+        }
+    }
+
+    if ( p_metavalues->i_count < p_metavalues->i_size )
+    {
+        p_metavalues->ppsz_values[p_metavalues->i_count] = (psz_val) ? strdup(psz_val) : NULL;
+        p_metavalues->i_count++;
+    }
+}
+
+static void vlc_meta_values_empty( vlc_meta_values_t * const p_metavalues )
+{
+    for (uint8_t i=0; i<p_metavalues->i_count; i++)
+        free(p_metavalues->ppsz_values[i]);
+    p_metavalues->i_count = 0;
+}
+
+/* releases values and storage */
+static void vlc_meta_values_free( vlc_meta_values_t * const p_metavalues )
+{
+    vlc_meta_values_empty( p_metavalues );
+    free(p_metavalues->ppsz_values);
+    p_metavalues->i_size = 0;
+}
+
 
 /**
  * vlc_meta contructor.
@@ -91,8 +144,8 @@ vlc_meta_t *vlc_meta_New( void )
     vlc_meta_t *m = (vlc_meta_t*)malloc( sizeof(*m) );
     if( !m )
         return NULL;
-    memset( m->ppsz_meta, 0, sizeof(m->ppsz_meta) );
     m->i_status = 0;
+    memset( m->rg_metavals, 0, sizeof(m->rg_metavals) );
     vlc_dictionary_init( &m->extra_tags, 0 );
     return m;
 }
@@ -106,9 +159,9 @@ static void vlc_meta_FreeExtraKey( void *p_data, void *p_obj )
 
 void vlc_meta_Delete( vlc_meta_t *m )
 {
-    int i;
-    for( i = 0; i < VLC_META_TYPE_COUNT ; i++ )
-        free( m->ppsz_meta[i] );
+    for( int i = 0; i < VLC_META_TYPE_COUNT; i++ )
+        vlc_meta_values_free( &m->rg_metavals[i] );
+
     vlc_dictionary_clear( &m->extra_tags, vlc_meta_FreeExtraKey, NULL );
     free( m );
 }
@@ -119,16 +172,36 @@ void vlc_meta_Delete( vlc_meta_t *m )
  * FIXME - Why don't we merge those two?
  */
 
+void vlc_meta_Add( vlc_meta_t *p_meta, vlc_meta_type_t meta_type, const char *psz_val )
+{
+    assert( psz_val == NULL || IsUTF8( psz_val ) );
+
+    vlc_meta_values_t *p_metavalues = &p_meta->rg_metavals[ meta_type ];
+    vlc_meta_values_add( p_metavalues, psz_val );
+}
+
 void vlc_meta_Set( vlc_meta_t *p_meta, vlc_meta_type_t meta_type, const char *psz_val )
 {
-    free( p_meta->ppsz_meta[meta_type] );
     assert( psz_val == NULL || IsUTF8( psz_val ) );
-    p_meta->ppsz_meta[meta_type] = psz_val ? strdup( psz_val ) : NULL;
+
+    vlc_meta_values_t *p_metavalues = &p_meta->rg_metavals[ meta_type ];
+    vlc_meta_values_empty( p_metavalues );
+    vlc_meta_Add( p_meta, meta_type, psz_val );
 }
 
 const char *vlc_meta_Get( const vlc_meta_t *p_meta, vlc_meta_type_t meta_type )
 {
-    return p_meta->ppsz_meta[meta_type];
+    const vlc_meta_values_t *p_metavalues = &p_meta->rg_metavals[ meta_type ];
+    return (p_metavalues && p_metavalues->i_count) ? p_metavalues->ppsz_values[0] : NULL;
+}
+
+const char ** vlc_meta_GetList( const vlc_meta_t *p_meta, vlc_meta_type_t meta_type, size_t * pi_nb )
+{
+    *pi_nb = p_meta->rg_metavals[ meta_type ].i_count;
+    if (! *pi_nb)
+        return NULL;
+    else
+        return (const char **) p_meta->rg_metavals[ meta_type ].ppsz_values;
 }
 
 void vlc_meta_AddExtra( vlc_meta_t *m, const char *psz_name, const char *psz_value )
@@ -182,10 +255,11 @@ void vlc_meta_Merge( vlc_meta_t *dst, const vlc_meta_t *src )
 
     for( i = 0; i < VLC_META_TYPE_COUNT; i++ )
     {
-        if( src->ppsz_meta[i] )
+        if( src->rg_metavals[i].i_count )
         {
-            free( dst->ppsz_meta[i] );
-            dst->ppsz_meta[i] = strdup( src->ppsz_meta[i] );
+            vlc_meta_values_empty( &dst->rg_metavals[i] );
+            for (uint8_t j=0; j<src->rg_metavals[i].i_count; j++)
+                vlc_meta_values_add( &dst->rg_metavals[i], src->rg_metavals[i].ppsz_values[j] );
         }
     }
 
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index bdd7b06..3497a44 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -533,10 +533,12 @@ vlc_iconv_open
 vlc_join
 vlc_list_children
 vlc_list_release
+vlc_meta_Add
 vlc_meta_AddExtra
 vlc_meta_CopyExtraNames
 vlc_meta_Delete
 vlc_meta_Get
+vlc_meta_GetList
 vlc_meta_GetExtra
 vlc_meta_GetExtraCount
 vlc_meta_GetStatus
-- 
1.9.3




More information about the vlc-devel mailing list