]> git.sesse.net Git - vlc/blobdiff - lib/media.c
input: Add support for AlbumArtist meta
[vlc] / lib / media.c
index 03f49df5a06e28fd04675815d3091ecb3426daa2..3caaf5b98046b8c887af12c35e9c0283a51373c5 100644 (file)
@@ -1,24 +1,24 @@
 /*****************************************************************************
  * media.c: Libvlc API media descripor management
  *****************************************************************************
- * Copyright (C) 2007 the VideoLAN team
+ * Copyright (C) 2007 VLC authors and VideoLAN
  * $Id$
  *
  * Authors: Pierre d'Herbemont <pdherbemont@videolan.org>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -26,6 +26,7 @@
 #endif
 
 #include <assert.h>
+#include <errno.h>
 
 #include <vlc/libvlc.h>
 #include <vlc/libvlc_media.h>
@@ -61,7 +62,14 @@ static const vlc_meta_type_t libvlc_to_vlc_meta[] =
     [libvlc_meta_Publisher]    = vlc_meta_Publisher,
     [libvlc_meta_EncodedBy]    = vlc_meta_EncodedBy,
     [libvlc_meta_ArtworkURL]   = vlc_meta_ArtworkURL,
-    [libvlc_meta_TrackID]      = vlc_meta_TrackID
+    [libvlc_meta_TrackID]      = vlc_meta_TrackID,
+    [libvlc_meta_TrackTotal]   = vlc_meta_TrackTotal,
+    [libvlc_meta_Director]     = vlc_meta_Director,
+    [libvlc_meta_Season]       = vlc_meta_Season,
+    [libvlc_meta_Episode]      = vlc_meta_Episode,
+    [libvlc_meta_ShowName]     = vlc_meta_ShowName,
+    [libvlc_meta_Actors]       = vlc_meta_Actors,
+    [libvlc_meta_AlbumArtist]  = vlc_meta_AlbumArtist
 };
 
 static const libvlc_meta_t vlc_to_libvlc_meta[] =
@@ -82,7 +90,14 @@ static const libvlc_meta_t vlc_to_libvlc_meta[] =
     [vlc_meta_Publisher]    = libvlc_meta_Publisher,
     [vlc_meta_EncodedBy]    = libvlc_meta_EncodedBy,
     [vlc_meta_ArtworkURL]   = libvlc_meta_ArtworkURL,
-    [vlc_meta_TrackID]      = libvlc_meta_TrackID
+    [vlc_meta_TrackID]      = libvlc_meta_TrackID,
+    [vlc_meta_TrackTotal]   = libvlc_meta_TrackTotal,
+    [vlc_meta_Director]     = libvlc_meta_Director,
+    [vlc_meta_Season]       = libvlc_meta_Season,
+    [vlc_meta_Episode]      = libvlc_meta_Episode,
+    [vlc_meta_ShowName]     = libvlc_meta_ShowName,
+    [vlc_meta_Actors]       = libvlc_meta_Actors,
+    [vlc_meta_AlbumArtist]  = libvlc_meta_AlbumArtist
 };
 
 /**************************************************************************
@@ -100,15 +115,14 @@ static void input_item_subitem_added( const vlc_event_t *p_event,
                 p_event->u.input_item_subitem_added.p_new_child );
 
     /* Add this to our media list */
-    if( !p_md->p_subitems )
+    if( p_md->p_subitems == NULL )
     {
         p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance );
+        if( unlikely(p_md->p_subitems == NULL) )
+            abort();
         libvlc_media_list_set_media( p_md->p_subitems, p_md );
     }
-    if( p_md->p_subitems )
-    {
-        libvlc_media_list_add_media( p_md->p_subitems, p_md_child );
-    }
+    libvlc_media_list_add_media( p_md->p_subitems, p_md_child );
 
     /* Construct the event */
     event.type = libvlc_MediaSubItemAdded;
@@ -119,6 +133,24 @@ static void input_item_subitem_added( const vlc_event_t *p_event,
     libvlc_media_release( p_md_child );
 }
 
+/**************************************************************************
+ * input_item_subitemtree_added (Private) (vlc event Callback)
+ **************************************************************************/
+static void input_item_subitemtree_added( const vlc_event_t * p_event,
+                                          void * user_data )
+{
+    VLC_UNUSED( p_event );
+    libvlc_media_t * p_md = user_data;
+    libvlc_event_t event;
+
+    /* Construct the event */
+    event.type = libvlc_MediaSubItemTreeAdded;
+    event.u.media_subitemtree_added.item = p_md;
+
+    /* Send the event */
+    libvlc_event_send( p_md->p_event_manager, &event );
+}
+
 /**************************************************************************
  * input_item_meta_changed (Private) (vlc event Callback)
  **************************************************************************/
@@ -201,6 +233,10 @@ static void install_input_item_observer( libvlc_media_t *p_md )
                       vlc_InputItemPreparsedChanged,
                       input_item_preparsed_changed,
                       p_md );
+    vlc_event_attach( &p_md->p_input_item->event_manager,
+                      vlc_InputItemSubItemTreeAdded,
+                      input_item_subitemtree_added,
+                      p_md );
 }
 
 /**************************************************************************
@@ -224,6 +260,10 @@ static void uninstall_input_item_observer( libvlc_media_t *p_md )
                       vlc_InputItemPreparsedChanged,
                       input_item_preparsed_changed,
                       p_md );
+    vlc_event_detach( &p_md->p_input_item->event_manager,
+                      vlc_InputItemSubItemTreeAdded,
+                      input_item_subitemtree_added,
+                      p_md );
 }
 
 /**************************************************************************
@@ -277,6 +317,7 @@ libvlc_media_t * libvlc_media_new_from_input_item(
     libvlc_event_manager_register_event_type(em, libvlc_MediaDurationChanged);
     libvlc_event_manager_register_event_type(em, libvlc_MediaStateChanged);
     libvlc_event_manager_register_event_type(em, libvlc_MediaParsedChanged);
+    libvlc_event_manager_register_event_type(em, libvlc_MediaSubItemTreeAdded);
 
     vlc_gc_incref( p_md->p_input_item );
 
@@ -313,10 +354,10 @@ libvlc_media_t *libvlc_media_new_location( libvlc_instance_t *p_instance,
 libvlc_media_t *libvlc_media_new_path( libvlc_instance_t *p_instance,
                                        const char *path )
 {
-    char *mrl = make_URI( path, "file" );
+    char *mrl = vlc_path2uri( path, NULL );
     if( unlikely(mrl == NULL) )
     {
-        libvlc_printerr( "Not enough memory" );
+        libvlc_printerr( "%s", vlc_strerror_c(errno) );
         return NULL;
     }
 
@@ -475,8 +516,7 @@ void libvlc_media_set_meta( libvlc_media_t *p_md, libvlc_meta_t e_meta, const ch
 int libvlc_media_save_meta( libvlc_media_t *p_md )
 {
     assert( p_md );
-    vlc_object_t *p_obj = VLC_OBJECT(libvlc_priv(
-                            p_md->p_libvlc_instance->p_libvlc_int)->p_playlist);
+    vlc_object_t *p_obj = VLC_OBJECT(p_md->p_libvlc_instance->p_libvlc_int);
     return input_item_WriteMeta( p_obj, p_md->p_input_item ) == VLC_SUCCESS;
 }
 
@@ -591,13 +631,12 @@ libvlc_media_get_duration( libvlc_media_t * p_md )
 
 static int media_parse(libvlc_media_t *media)
 {
-    /* TODO: fetcher and parser independent of playlist */
-    playlist_t *playlist =
-        libvlc_priv (media->p_libvlc_instance->p_libvlc_int)->p_playlist;
+    libvlc_int_t *libvlc = media->p_libvlc_instance->p_libvlc_int;
+    input_item_t *item = media->p_input_item;
 
     /* TODO: Fetch art on need basis. But how not to break compatibility? */
-    playlist_AskForArtEnqueue(playlist, media->p_input_item );
-    return playlist_PreparseEnqueue(playlist, media->p_input_item);
+    libvlc_ArtRequest(libvlc, item, META_REQUEST_OPTION_NONE);
+    return libvlc_MetaRequest(libvlc, item, META_REQUEST_OPTION_NONE);
 }
 
 /**************************************************************************
@@ -735,3 +774,116 @@ libvlc_media_get_tracks_info( libvlc_media_t *p_md, libvlc_media_track_info_t **
     vlc_mutex_unlock( &p_input_item->lock );
     return i_es;
 }
+
+unsigned
+libvlc_media_tracks_get( libvlc_media_t *p_md, libvlc_media_track_t *** pp_es )
+{
+    assert( p_md );
+
+    input_item_t *p_input_item = p_md->p_input_item;
+    vlc_mutex_lock( &p_input_item->lock );
+
+    const int i_es = p_input_item->i_es;
+    *pp_es = (i_es > 0) ? calloc( i_es, sizeof(**pp_es) ) : NULL;
+
+    if( !*pp_es ) /* no ES, or OOM */
+    {
+        vlc_mutex_unlock( &p_input_item->lock );
+        return 0;
+    }
+
+    /* Fill array */
+    for( int i = 0; i < i_es; i++ )
+    {
+        libvlc_media_track_t *p_mes = calloc( 1, sizeof(*p_mes) );
+        if ( p_mes )
+        {
+            p_mes->audio = malloc( __MAX(__MAX(sizeof(*p_mes->audio),
+                                               sizeof(*p_mes->video)),
+                                               sizeof(*p_mes->subtitle)) );
+        }
+        if ( !p_mes || !p_mes->audio )
+        {
+            libvlc_media_tracks_release( *pp_es, i_es );
+            *pp_es = NULL;
+            free( p_mes );
+            vlc_mutex_unlock( &p_input_item->lock );
+            return 0;
+        }
+        (*pp_es)[i] = p_mes;
+
+        const es_format_t *p_es = p_input_item->es[i];
+
+        p_mes->i_codec = p_es->i_codec;
+        p_mes->i_original_fourcc = p_es->i_original_fourcc;
+        p_mes->i_id = p_es->i_id;
+
+        p_mes->i_profile = p_es->i_profile;
+        p_mes->i_level = p_es->i_level;
+
+        p_mes->i_bitrate = p_es->i_bitrate;
+        p_mes->psz_language = p_es->psz_language != NULL ? strdup(p_es->psz_language) : NULL;
+        p_mes->psz_description = p_es->psz_description != NULL ? strdup(p_es->psz_description) : NULL;
+
+        switch(p_es->i_cat)
+        {
+        case UNKNOWN_ES:
+        default:
+            p_mes->i_type = libvlc_track_unknown;
+            break;
+        case VIDEO_ES:
+            p_mes->i_type = libvlc_track_video;
+            p_mes->video->i_height = p_es->video.i_height;
+            p_mes->video->i_width = p_es->video.i_width;
+            p_mes->video->i_sar_num = p_es->video.i_sar_num;
+            p_mes->video->i_sar_den = p_es->video.i_sar_den;
+            p_mes->video->i_frame_rate_num = p_es->video.i_frame_rate;
+            p_mes->video->i_frame_rate_den = p_es->video.i_frame_rate_base;
+            break;
+        case AUDIO_ES:
+            p_mes->i_type = libvlc_track_audio;
+            p_mes->audio->i_channels = p_es->audio.i_channels;
+            p_mes->audio->i_rate = p_es->audio.i_rate;
+            break;
+        case SPU_ES:
+            p_mes->i_type = libvlc_track_text;
+            p_mes->subtitle->psz_encoding = p_es->subs.psz_encoding != NULL ?
+                                            strdup(p_es->subs.psz_encoding) : NULL;
+            break;
+        }
+    }
+
+    vlc_mutex_unlock( &p_input_item->lock );
+    return i_es;
+}
+
+
+/**************************************************************************
+ * Release media descriptor's elementary streams description array
+ **************************************************************************/
+void libvlc_media_tracks_release( libvlc_media_track_t **p_tracks, unsigned i_count )
+{
+    for( unsigned i = 0; i < i_count; ++i )
+    {
+        if ( !p_tracks[i] )
+            continue;
+        free( p_tracks[i]->psz_language );
+        free( p_tracks[i]->psz_description );
+        switch( p_tracks[i]->i_type )
+        {
+        case libvlc_track_audio:
+            break;
+        case libvlc_track_video:
+            break;
+        case libvlc_track_text:
+            free( p_tracks[i]->subtitle->psz_encoding );
+            break;
+        case libvlc_track_unknown:
+        default:
+            break;
+        }
+        free( p_tracks[i]->audio );
+        free( p_tracks[i] );
+    }
+    free( p_tracks );
+}