libvlc: expand media player API to retrieve full information about available chapter...
authorFelix Paul Kühne <fkuehne@videolan.org>
Thu, 4 Jun 2015 12:02:44 +0000 (14:02 +0200)
committerFelix Paul Kühne <fkuehne@videolan.org>
Tue, 9 Jun 2015 15:58:14 +0000 (17:58 +0200)
NEWS
include/vlc/libvlc_media_player.h
include/vlc_input.h
lib/libvlc.sym
lib/media_player.c
src/input/control.c

diff --git a/NEWS b/NEWS
index fadc7e6..4b87f6e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -120,7 +120,8 @@ libVLC:
    identifier (if there is one available)
  * Add libvlc_media_get_type to get the type of the media
  * Add libvlc_media_player_get_full_title_descriptions to get full title info of the media
- * Deprecate libvlc_video_get_title_description
+ * Add libvlc_media_player_get_full_chapter_descriptions to get full chapter info of the media
+ * Deprecate libvlc_video_get_title_description, libvlc_video_get_chapter_description
 
 Logging
  * Support for the SystemD Journal
index d0c2120..5f96b1b 100644 (file)
@@ -72,6 +72,18 @@ typedef struct libvlc_title_description_t
     bool b_menu;
 } libvlc_title_description_t;
 
+/**
+ * Description for chapters.
+ * It contains information about time offset, duration
+ * (both in milliseconds) as well as name (description string).
+ */
+typedef struct libvlc_chapter_description_t
+{
+    int64_t i_time_offset;
+    int64_t i_duration;
+    char *psz_name;
+} libvlc_chapter_description_t;
+
 /**
  * Description for audio output. It contains
  * name, description and pointer to next record.
@@ -1169,6 +1181,35 @@ LIBVLC_API
     void libvlc_title_descriptions_release( libvlc_title_description_t **p_titles,
                                             unsigned i_count );
 
+/**
+ * Get the full description of available chapters
+ *
+ * \version LibVLC 3.0.0 and later.
+ *
+ * \param p_mi the media player
+ * \param index of the title to query for chapters
+ * \param address to store an allocated array of chapter descriptions
+ *        descriptions (must be freed with libvlc_chapter_descriptions_release()
+ *        by the caller) [OUT]
+ *
+ * \return the number of chapters (-1 on error)
+ */
+LIBVLC_API int libvlc_media_player_get_full_chapter_descriptions( libvlc_media_player_t *p_mi,
+                                                                  int i_chapters_of_title,
+                                                                  libvlc_chapter_description_t *** pp_chapters );
+
+/**
+ * Release a chapter description
+ *
+ * \version LibVLC 3.0.0 and later
+ *
+ * \param chapter description array to release
+ * \param number of chapter descriptions to release
+ */
+LIBVLC_API
+void libvlc_chapter_descriptions_release( libvlc_chapter_description_t **p_chapters,
+                                          unsigned i_count );
+
 /**
  * Get the description of available chapters for specific title.
  *
@@ -1177,7 +1218,7 @@ LIBVLC_API
  * \return list containing description of available chapter for title i_title.
  * It must be freed with libvlc_track_description_list_release()
  */
-LIBVLC_API libvlc_track_description_t *
+LIBVLC_DEPRECATED LIBVLC_API libvlc_track_description_t *
         libvlc_video_get_chapter_description( libvlc_media_player_t *p_mi, int i_title );
 
 /**
index 4a397fc..7ae07b1 100644 (file)
@@ -455,6 +455,9 @@ enum input_query_e
     INPUT_GET_TITLE_INFO,     /* arg1=input_title_t** arg2= int * res=can fail */
     INPUT_GET_FULL_TITLE_INFO,     /* arg1=input_title_t*** arg2= int * res=can fail */
 
+    /* seekpoints */
+    INPUT_GET_SEEKPOINTS,  /* arg1=seekpoint_t*** arg2= int * res=can fail */
+
     /* Attachments */
     INPUT_GET_ATTACHMENTS, /* arg1=input_attachment_t***, arg2=int*  res=can fail */
     INPUT_GET_ATTACHMENT,  /* arg1=input_attachment_t**, arg2=char*  res=can fail */
index 44e0eda..03577c7 100644 (file)
@@ -44,6 +44,7 @@ libvlc_audio_set_format
 libvlc_audio_set_format_callbacks
 libvlc_audio_set_callbacks
 libvlc_audio_set_volume_callback
+libvlc_chapter_descriptions_release
 libvlc_clock
 libvlc_event_attach
 libvlc_event_detach
@@ -149,6 +150,7 @@ libvlc_media_player_get_chapter
 libvlc_media_player_get_chapter_count
 libvlc_media_player_get_chapter_count_for_title
 libvlc_media_player_get_fps
+libvlc_media_player_get_full_chapter_descriptions
 libvlc_media_player_get_full_title_descriptions
 libvlc_media_player_get_hwnd
 libvlc_media_player_get_length
index 4e17b19..9c88996 100644 (file)
@@ -1408,6 +1408,92 @@ void libvlc_title_descriptions_release( libvlc_title_description_t **p_titles,
     free( p_titles );
 }
 
+int libvlc_media_player_get_full_chapter_descriptions( libvlc_media_player_t *p_mi,
+                                                      int i_chapters_of_title,
+                                                      libvlc_chapter_description_t *** pp_chapters )
+{
+    assert( p_mi );
+
+    input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
+
+    if( !p_input_thread )
+        return -1;
+
+    seekpoint_t **p_seekpoint = NULL;
+
+    /* fetch data */
+    int ret = input_Control(p_input_thread, INPUT_GET_SEEKPOINTS, &p_seekpoint, &i_chapters_of_title);
+    vlc_object_release( p_input_thread );
+
+    if( ret != VLC_SUCCESS)
+    {
+        return -1;
+    }
+
+    if (i_chapters_of_title == 0 || p_seekpoint == NULL)
+    {
+        return 0;
+    }
+
+    const int ci_chapter_count = (const int)i_chapters_of_title;
+
+    *pp_chapters = calloc( ci_chapter_count, sizeof(**pp_chapters) );
+    if( !*pp_chapters )
+    {
+        return -1;
+    }
+
+    /* fill array */
+    for( int i = 0; i < ci_chapter_count; i++)
+    {
+        libvlc_chapter_description_t *p_chapter = calloc( 1, sizeof(*p_chapter) );
+        if( unlikely(p_chapter == NULL) )
+        {
+            libvlc_chapter_descriptions_release( *pp_chapters, ci_chapter_count );
+            free( p_chapter );
+            return -1;
+        }
+        (*pp_chapters)[i] = p_chapter;
+
+        p_chapter->i_time_offset = p_seekpoint[i]->i_time_offset / 1000;
+
+        if( i > 0 )
+        {
+            p_chapter->i_duration = p_chapter->i_time_offset - (*pp_chapters)[i-1]->i_time_offset;
+        }
+        else
+        {
+            p_chapter->i_duration = p_chapter->i_time_offset;
+        }
+
+        if( p_seekpoint[i]->psz_name )
+        {
+            p_chapter->psz_name = strdup( p_seekpoint[i]->psz_name );
+        }
+        else
+        {
+            p_chapter->psz_name = NULL;
+        }
+        vlc_seekpoint_Delete( p_seekpoint[i] );
+    }
+
+    return ci_chapter_count;
+}
+
+void libvlc_chapter_descriptions_release( libvlc_chapter_description_t **p_chapters,
+                                          unsigned i_count )
+{
+    for (unsigned i = 0; i < i_count; i++ )
+    {
+        if ( !p_chapters[i] )
+            continue;
+
+        free( p_chapters[i]->psz_name );
+        free( p_chapters[i] );
+    }
+    free( p_chapters );
+}
+
 void libvlc_media_player_next_chapter( libvlc_media_player_t *p_mi )
 {
     input_thread_t *p_input_thread;
index 72656f4..dc33492 100644 (file)
@@ -391,6 +391,50 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
             return VLC_SUCCESS;
         }
 
+        case INPUT_GET_SEEKPOINTS:
+        {
+            seekpoint_t ***array = (seekpoint_t ***)va_arg( args, seekpoint_t *** );
+            int *pi_title_to_fetch = (int *) va_arg( args, int * );
+
+            vlc_mutex_lock( &p_input->p->p_item->lock );
+
+            if ( *pi_title_to_fetch < 0 ) /* query current title if -1 */
+                *pi_title_to_fetch = var_GetInteger( p_input, "title" );
+
+            if( !p_input->p->i_title || p_input->p->i_title < *pi_title_to_fetch )
+            {
+                vlc_mutex_unlock( &p_input->p->p_item->lock );
+                return VLC_EGENERIC;
+            }
+
+            input_title_t *p_title = vlc_input_title_Duplicate( p_input->p->title[*pi_title_to_fetch] );
+
+            /* set arg2 to the number of seekpoints we found */
+            const int i_chapters = p_title->i_seekpoint;
+            *pi_title_to_fetch = i_chapters;
+
+            if ( i_chapters == 0 )
+            {
+                vlc_mutex_unlock( &p_input->p->p_item->lock );
+                return VLC_SUCCESS;
+            }
+
+            *array = calloc( p_title->i_seekpoint, sizeof(**array) );
+            if( !array )
+            {
+                vlc_mutex_unlock( &p_input->p->p_item->lock );
+                return VLC_ENOMEM;
+            }
+            for( int i = 0; i < i_chapters; i++ )
+            {
+                (*array)[i] = vlc_seekpoint_Duplicate( p_title->seekpoint[i] );
+            }
+
+            vlc_mutex_unlock( &p_input->p->p_item->lock );
+
+            return VLC_SUCCESS;
+        }
+
         case INPUT_GET_VIDEO_FPS:
             pf = (double*)va_arg( args, double * );