+/* internal function, used by audio, video */
+libvlc_track_description_t *
+ libvlc_get_track_description( libvlc_media_player_t *p_mi,
+ const char *psz_variable,
+ libvlc_exception_t *p_e )
+{
+ input_thread_t *p_input = libvlc_get_input_thread( p_mi, p_e );
+
+ if( !p_input )
+ return NULL;
+
+ vlc_value_t val_list, text_list;
+ var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list);
+
+ if( val_list.p_list->i_count <= 0 ) /* no tracks */
+ return NULL;
+
+ libvlc_track_description_t *p_track_description, *p_actual, *p_previous;
+ p_track_description = ( libvlc_track_description_t * )
+ malloc( sizeof( libvlc_track_description_t ) );
+ if ( !p_track_description )
+ {
+ var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
+ vlc_object_release( p_input );
+ libvlc_exception_raise( p_e, "no enough memory" );
+ return NULL;
+ }
+ p_actual = p_track_description;
+ p_previous = NULL;
+ for( int i = 0; i < val_list.p_list->i_count; i++ )
+ {
+ if( !p_actual )
+ {
+ p_actual = ( libvlc_track_description_t * )
+ malloc( sizeof( libvlc_track_description_t ) );
+ if ( !p_actual )
+ {
+ libvlc_track_description_release( p_track_description );
+ var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
+ vlc_object_release( p_input );
+ libvlc_exception_raise( p_e, "no enough memory" );
+ return NULL;
+ }
+ }
+ p_actual->i_id = val_list.p_list->p_values[i].i_int;
+ p_actual->psz_name = strdup( text_list.p_list->p_values[i].psz_string );
+ p_actual->p_next = NULL;
+ if( p_previous )
+ p_previous->p_next = p_actual;
+ p_previous = p_actual;
+ p_actual = NULL;
+ }
+ var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
+ vlc_object_release( p_input );
+
+ return p_track_description;
+}
+
+void libvlc_track_description_release( libvlc_track_description_t *p_track_description )
+{
+ libvlc_track_description_t *p_actual, *p_before;
+ p_actual = p_track_description;
+
+ while ( p_actual )
+ {
+ free( p_actual->psz_name );
+ p_before = p_actual;
+ p_actual = p_before->p_next;
+ free( p_before );
+ }
+}
+