[vlc-devel] [PATCH] Adjusted meta data signalling to only send events when the meta data has actually changed.

Johannes Marbach johannesmarbach at googlemail.com
Wed Oct 12 13:52:39 CEST 2011


The emission of vlc_InputItemMetaChanged signals has been limited to cases in which the meta data has actually changed. Unset meta fields (null pointers) are treated as empty strings. The vlc_meta_Merge function has been forked into vlc_meta_MergeAndRemember, which gives the caller access to the meta types that were changed during the merge.
---
 include/vlc_meta.h |    3 +++
 src/input/es_out.c |   32 ++++++++++++++++++++++----------
 src/input/event.c  |    4 ++--
 src/input/event.h  |    2 +-
 src/input/input.c  |    6 +++---
 src/input/meta.c   |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 78 insertions(+), 16 deletions(-)

diff --git a/include/vlc_meta.h b/include/vlc_meta.h
index a5278e7..e5672aa 100644
--- a/include/vlc_meta.h
+++ b/include/vlc_meta.h
@@ -79,6 +79,9 @@ VLC_API unsigned vlc_meta_GetExtraCount( const vlc_meta_t *m );
 VLC_API char ** vlc_meta_CopyExtraNames( const vlc_meta_t *m ) VLC_USED;
 
 VLC_API void vlc_meta_Merge( vlc_meta_t *dst, const vlc_meta_t *src );
+VLC_API void vlc_meta_MergeAndRemember( vlc_meta_t *dst, const vlc_meta_t *src,
+                                        vlc_meta_type_t **p_changed_types, int *p_i_n_changed_types);
+VLC_API int vlc_meta_CompareValues( char* psz1, char* psz2 );
 
 VLC_API int vlc_meta_GetStatus( vlc_meta_t *m );
 VLC_API void vlc_meta_SetStatus( vlc_meta_t *m, int status );
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 760e57b..d856f3a 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -1045,10 +1045,12 @@ static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm )
     }
 
     /* Update now playing */
-    input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
-    input_item_SetPublisher( p_input->p->p_item, p_pgrm->psz_publisher );
+    if( vlc_meta_CompareValues( input_item_GetNowPlaying( p_input->p->p_item ), p_pgrm->psz_now_playing ) )
+        input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
 
-    input_SendEventMeta( p_input );
+    /* Update publisher */
+    if( vlc_meta_CompareValues( input_item_GetPublisher( p_input->p->p_item ), p_pgrm->psz_publisher ) )
+        input_item_SetPublisher( p_input->p->p_item, p_pgrm->psz_publisher );
 }
 
 /* EsOutAddProgram:
@@ -1267,8 +1269,8 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, const vlc_meta_t *p_me
     {
         if( p_sys->p_pgrm == p_pgrm )
         {
-            input_item_SetPublisher( p_input->p->p_item, psz_provider );
-            input_SendEventMeta( p_input );
+            if( vlc_meta_CompareValues( input_item_GetPublisher( p_input->p->p_item ), psz_provider ) )
+                input_item_SetPublisher( p_input->p->p_item, psz_provider );
         }
         if( p_cat )
             info_category_AddInfo( p_cat, vlc_meta_TypeToLocalizedString(vlc_meta_Publisher),
@@ -1326,8 +1328,8 @@ static void EsOutProgramEpg( es_out_t *out, int i_group, const vlc_epg_t *p_epg
 
     if( p_pgrm == p_sys->p_pgrm )
     {
-        input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
-        input_SendEventMeta( p_input );
+        if( vlc_meta_CompareValues( input_item_GetNowPlaying( p_input->p->p_item ), p_pgrm->psz_now_playing ) )
+            input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
     }
 
     if( p_pgrm->psz_now_playing )
@@ -1388,9 +1390,12 @@ static void EsOutMeta( es_out_t *p_out, const vlc_meta_t *p_meta )
     if( vlc_meta_Get( p_meta, vlc_meta_Title ) && !p_item->b_fixed_name )
         psz_title = strdup( vlc_meta_Get( p_meta, vlc_meta_Title ) );
 
-    vlc_meta_Merge( p_item->p_meta, p_meta );
+    /* Merge meta data & remember changed fields */
+    vlc_meta_type_t *p_changed_types = 0;
+    int i_n_changed_types;
+    vlc_meta_MergeAndRemember( p_item->p_meta, p_meta, &p_changed_types, &i_n_changed_types );
 
-    if( !psz_arturl || *psz_arturl == '\0' )
+    if( p_item->p_meta && (!psz_arturl || *psz_arturl == '\0') )
     {
         const char *psz_tmp = vlc_meta_Get( p_item->p_meta, vlc_meta_ArtworkURL );
         if( psz_tmp )
@@ -1421,7 +1426,14 @@ static void EsOutMeta( es_out_t *p_out, const vlc_meta_t *p_meta )
     }
     input_item_SetPreparsed( p_item, true );
 
-    input_SendEventMeta( p_input );
+    if( p_changed_types )
+    {
+        /* Send meta changed event for each updated field */
+        int i;
+        for( i = 0; i < i_n_changed_types; ++i )
+            input_SendEventMeta( p_input, p_changed_types[i] );
+        free( p_changed_types );
+    }
     /* TODO handle sout meta ? */
 }
 
diff --git a/src/input/event.c b/src/input/event.c
index f0a4205..d0dde39 100644
--- a/src/input/event.c
+++ b/src/input/event.c
@@ -198,7 +198,7 @@ void input_SendEventCache( input_thread_t *p_input, double f_level )
 /* FIXME: review them because vlc_event_send might be
  * moved inside input_item* functions.
  */
-void input_SendEventMeta( input_thread_t *p_input )
+void input_SendEventMeta( input_thread_t *p_input, vlc_meta_type_t type )
 {
     Trigger( p_input, INPUT_EVENT_ITEM_META );
 
@@ -206,7 +206,7 @@ void input_SendEventMeta( input_thread_t *p_input )
     vlc_event_t event;
 
     event.type = vlc_InputItemMetaChanged;
-    event.u.input_item_meta_changed.meta_type = vlc_meta_ArtworkURL;
+    event.u.input_item_meta_changed.meta_type = type;
     vlc_event_send( &p_input->p->p_item->event_manager, &event );
 }
 
diff --git a/src/input/event.h b/src/input/event.h
index 31eea4d..27c7acc 100644
--- a/src/input/event.h
+++ b/src/input/event.h
@@ -45,7 +45,7 @@ void input_SendEventState( input_thread_t *p_input, int i_state );
 void input_SendEventCache( input_thread_t *p_input, double f_level );
 
 /* TODO rename Item* */
-void input_SendEventMeta( input_thread_t *p_input );
+void input_SendEventMeta( input_thread_t *p_input, vlc_meta_type_t type );
 void input_SendEventMetaInfo( input_thread_t *p_input );
 void input_SendEventMetaName( input_thread_t *p_input, const char *psz_name );
 void input_SendEventMetaEpg( input_thread_t *p_input );
diff --git a/src/input/input.c b/src/input/input.c
index b43df74..b05384a 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -475,9 +475,9 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
         }
     }
 
-    /* Remove 'Now playing' info as it is probably outdated */
-    input_item_SetNowPlaying( p_item, NULL );
-    input_SendEventMeta( p_input );
+    /* Remove 'Now playing' info in case it is outdated */
+    if( vlc_meta_CompareValues( input_item_GetNowPlaying( p_item ), 0 ) )
+        input_item_SetNowPlaying( p_item, NULL );
 
     /* */
     if( p_input->b_preparsing )
diff --git a/src/input/meta.c b/src/input/meta.c
index 5d7e980..853c223 100644
--- a/src/input/meta.c
+++ b/src/input/meta.c
@@ -195,6 +195,53 @@ void vlc_meta_Merge( vlc_meta_t *dst, const vlc_meta_t *src )
     free( ppsz_all_keys );
 }
 
+void vlc_meta_MergeAndRemember( vlc_meta_t *dst, const vlc_meta_t *src,
+                                vlc_meta_type_t **p_changed_types, int *p_i_n_changed_types)
+{
+    char **ppsz_all_keys;
+    int i;
+    *p_changed_types = 0;
+    *p_i_n_changed_types = 0;
+    
+    if( !dst || !src )
+        return;
+    
+    for( i = 0; i < VLC_META_TYPE_COUNT; i++ )
+    {
+        if( src->ppsz_meta[i] )
+        {
+            if( vlc_meta_CompareValues( src->ppsz_meta[i], dst->ppsz_meta[i] ) )
+            {
+                *p_i_n_changed_types += 1;
+                *p_changed_types = realloc( *p_changed_types, (*p_i_n_changed_types) * sizeof( vlc_meta_type_t ) );
+                (*p_changed_types)[(*p_i_n_changed_types) - 1] = i;
+            }
+            
+            free( dst->ppsz_meta[i] );
+            dst->ppsz_meta[i] = strdup( src->ppsz_meta[i] );
+        }
+    }
+    
+    /* XXX: If speed up are needed, it is possible */
+    ppsz_all_keys = vlc_dictionary_all_keys( &src->extra_tags );
+    for( i = 0; ppsz_all_keys && ppsz_all_keys[i]; i++ )
+    {
+        /* Always try to remove the previous value */
+        vlc_dictionary_remove_value_for_key( &dst->extra_tags, ppsz_all_keys[i], vlc_meta_FreeExtraKey, NULL );
+        
+        void *p_value = vlc_dictionary_value_for_key( &src->extra_tags, ppsz_all_keys[i] );
+        vlc_dictionary_insert( &dst->extra_tags, ppsz_all_keys[i], strdup( (const char*)p_value ) );
+        free( ppsz_all_keys[i] );
+    }
+    free( ppsz_all_keys );
+}
+
+int vlc_meta_CompareValues( char* psz1, char* psz2 )
+{
+    /* Resolves null pointers to empty strings */
+    return strcmp( (psz1) ? psz1 : "\0", (psz2) ? psz2 : "\0" );
+}
+
 
 void input_ExtractAttachmentAndCacheArt( input_thread_t *p_input )
 {
-- 
1.7.7




More information about the vlc-devel mailing list