X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fplaylist%2Fsort.c;h=e7c5f6e116b056080cc8d00c0a6486ed24a70d04;hb=d2ac50af2227392073822d82d809d25a7f013152;hp=a4be1de8b224871d1eb7c88516c142b4c44e5551;hpb=315069b3b158b8d71668b5295e4fd0ea8957a3f2;p=vlc diff --git a/src/playlist/sort.c b/src/playlist/sort.c index a4be1de8b2..e7c5f6e116 100644 --- a/src/playlist/sort.c +++ b/src/playlist/sort.c @@ -1,10 +1,11 @@ /***************************************************************************** * sort.c : Playlist sorting functions ***************************************************************************** - * Copyright (C) 1999-2004 the VideoLAN team + * Copyright (C) 1999-2007 the VideoLAN team * $Id$ * * Authors: Clément Stenac + * Ilkka Ollakka * * 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 @@ -20,19 +21,22 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include #include "vlc_playlist.h" #include "playlist_internal.h" -int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, - playlist_item_t **pp_items, int i_mode, - int i_type ); +static int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, + playlist_item_t **pp_items, int i_mode, + int i_type ); +static int playlist_cmp(const void *, const void *); /** * Sort a node. - * * This function must be entered with the playlist lock ! * * \param p_playlist the playlist @@ -41,8 +45,8 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, * \param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order) * \return VLC_SUCCESS on success */ -int playlist_NodeSort( playlist_t * p_playlist , playlist_item_t *p_node, - int i_mode, int i_type ) +static int playlist_NodeSort( playlist_t * p_playlist , playlist_item_t *p_node, + int i_mode, int i_type ) { playlist_ItemArraySort( p_playlist,p_node->i_children, p_node->pp_children, i_mode, i_type ); @@ -76,15 +80,21 @@ int playlist_RecursiveNodeSort( playlist_t *p_playlist, playlist_item_t *p_node, return VLC_SUCCESS; } +static int sort_mode = 0; +static int sort_type = 0; -int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, - playlist_item_t **pp_items, int i_mode, - int i_type ) +static int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, + playlist_item_t **pp_items, int i_mode, + int i_type ) { - int i , i_small , i_position; + int i_position; playlist_item_t *p_temp; vlc_value_t val; - val.b_bool = VLC_TRUE; + val.b_bool = true; + sort_mode = i_mode; + sort_type = i_type; + + (void)p_playlist; // a bit surprising we don't need p_playlist! if( i_mode == SORT_RANDOM ) { @@ -103,24 +113,36 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, return VLC_SUCCESS; } + qsort(pp_items,i_items,sizeof(pp_items[0]),playlist_cmp); + return VLC_SUCCESS; +} + +static int playlist_cmp(const void *first, const void *second) +{ + +#define META_STRCASECMP_NAME( ) { \ + char *psz_i = input_item_GetName( (*(playlist_item_t **)first)->p_input ); \ + char *psz_ismall = input_item_GetName( (*(playlist_item_t **)second)->p_input ); \ + i_test = strcasecmp( psz_i, psz_ismall ); \ + free( psz_i ); \ + free( psz_ismall ); \ +} + -#define DO_META_SORT( node ) { \ - char *psz_a = pp_items[i]->p_input->p_meta ? \ - pp_items[i]->p_input->p_meta->psz_##node : NULL ; \ - char *psz_b = pp_items[i_small]->p_input->p_meta ? \ - pp_items[i_small]->p_input->p_meta->psz_##node : NULL; \ +#define DO_META_SORT_ADV( node, integer ) { \ + char *psz_a = input_item_GetMeta( (*(playlist_item_t **)first)->p_input, vlc_meta_##node ); \ + char *psz_b = input_item_GetMeta( (*(playlist_item_t **)second)->p_input, vlc_meta_##node ); \ /* Nodes go first */ \ - if( pp_items[i]->i_children == -1 && pp_items[i_small]->i_children >= 0 ) \ + if( (*(playlist_item_t **)first)->i_children == -1 && (*(playlist_item_t **)second)->i_children >= 0 ) \ i_test = 1;\ - else if( pp_items[i]->i_children >= 0 &&\ - pp_items[i_small]->i_children == -1 ) \ + else if( (*(playlist_item_t **)first)->i_children >= 0 &&\ + (*(playlist_item_t **)second)->i_children == -1 ) \ i_test = -1; \ /* Both are nodes, sort by name */ \ - else if( pp_items[i]->i_children >= 0 && \ - pp_items[i_small]->i_children >= 0 ) \ + else if( (*(playlist_item_t **)first)->i_children >= 0 && \ + (*(playlist_item_t **)second)->i_children >= 0 ) \ { \ - i_test = strcasecmp( pp_items[i]->p_input->psz_name, \ - pp_items[i_small]->p_input->psz_name ); \ + META_STRCASECMP_NAME( ) \ } \ /* Both are items */ \ else if( psz_a == NULL && psz_b != NULL ) \ @@ -130,75 +152,95 @@ int playlist_ItemArraySort( playlist_t *p_playlist, int i_items, /* No meta, sort by name */ \ else if( psz_a == NULL && psz_b == NULL ) \ { \ - i_test = strcasecmp( pp_items[i]->p_input->psz_name, \ - pp_items[i_small]->p_input->psz_name ); \ + META_STRCASECMP_NAME( ); \ } \ else \ { \ - i_test = strcmp( psz_b, psz_a ); \ + if( !integer ) i_test = strcmp( psz_a, psz_b ); \ + else i_test = atoi( psz_a ) - atoi( psz_b ); \ } \ + free( psz_a ); \ + free( psz_b ); \ } +#define DO_META_SORT( node ) DO_META_SORT_ADV( node, false ) - for( i_position = 0; i_position < i_items -1 ; i_position ++ ) + int i_test = 0; + + if( sort_mode == SORT_TITLE ) + { + META_STRCASECMP_NAME( ); + } + else if( sort_mode == SORT_TITLE_NUMERIC ) + { + char *psz_i = input_item_GetName( (*(playlist_item_t **)first)->p_input ); + char *psz_ismall = + input_item_GetName( (*(playlist_item_t **)second)->p_input ); + i_test = atoi( psz_i ) - atoi( psz_ismall ); + free( psz_i ); + free( psz_ismall ); + } + else if( sort_mode == SORT_DURATION ) + { + i_test = input_item_GetDuration( (*(playlist_item_t **)first)->p_input ) - + input_item_GetDuration( (*(playlist_item_t **)second)->p_input ); + } + else if( sort_mode == SORT_ARTIST ) + { + DO_META_SORT( Artist ); + /* sort by artist, album, tracknumber */ + if( i_test == 0 ) + DO_META_SORT( Album ); + if( i_test == 0 ) + DO_META_SORT_ADV( TrackNumber, true ); + } + else if( sort_mode == SORT_GENRE ) { - i_small = i_position; - for( i = i_position + 1 ; i< i_items ; i++) + DO_META_SORT( Genre ); + } + else if( sort_mode == SORT_ALBUM ) + { + DO_META_SORT( Album ); + /* Sort by tracknumber if albums are the same */ + if( i_test == 0 ) + DO_META_SORT_ADV( TrackNumber, true ); + } + else if( sort_mode == SORT_TRACK_NUMBER ) + { + DO_META_SORT_ADV( TrackNumber, true ); + } + else if( sort_mode == SORT_DESCRIPTION ) + { + DO_META_SORT( Description ); + } + else if( sort_mode == SORT_ID ) + { + i_test = (*(playlist_item_t **)first)->i_id - (*(playlist_item_t **)second)->i_id; + } + else if( sort_mode == SORT_TITLE_NODES_FIRST ) + { + /* Alphabetic sort, all nodes first */ + + if( (*(playlist_item_t **)first)->i_children == -1 && + (*(playlist_item_t **)second)->i_children >= 0 ) { - int i_test = 0; - - if( i_mode == SORT_TITLE ) - { - i_test = strcasecmp( pp_items[i]->p_input->psz_name, - pp_items[i_small]->p_input->psz_name ); - } - else if( i_mode == SORT_TITLE_NUMERIC ) - { - i_test = atoi( pp_items[i]->p_input->psz_name ) - - atoi( pp_items[i_small]->p_input->psz_name ); - } - else if( i_mode == SORT_DURATION ) - { - i_test = pp_items[i]->p_input->i_duration - - pp_items[i_small]->p_input->i_duration; - } - else if( i_mode == SORT_ARTIST ) - { - DO_META_SORT( artist ); - } - else if( i_mode == SORT_ALBUM ) - { - DO_META_SORT( album ); - } - else if( i_mode == SORT_TITLE_NODES_FIRST ) - { - /* Alphabetic sort, all nodes first */ - - if( pp_items[i]->i_children == -1 && - pp_items[i_small]->i_children >= 0 ) - { - i_test = 1; - } - else if( pp_items[i]->i_children >= 0 && - pp_items[i_small]->i_children == -1 ) - { - i_test = -1; - } - else - { - i_test = strcasecmp( pp_items[i]->p_input->psz_name, - pp_items[i_small]->p_input->psz_name ); - } - } - - if( ( i_type == ORDER_NORMAL && i_test < 0 ) || - ( i_type == ORDER_REVERSE && i_test > 0 ) ) - { - i_small = i; - } + i_test = 1; + } + else if( (*(playlist_item_t **)first)->i_children >= 0 && + (*(playlist_item_t **)second)->i_children == -1 ) + { + i_test = -1; + } + else + { + i_test = strcasecmp( (*(playlist_item_t **)first)->p_input->psz_name, + (*(playlist_item_t **)second)->p_input->psz_name ); } - p_temp = pp_items[i_position]; - pp_items[i_position] = pp_items[i_small]; - pp_items[i_small] = p_temp; } - return VLC_SUCCESS; + + if ( sort_type == ORDER_REVERSE ) + i_test = i_test * -1; +#undef DO_META_SORT +#undef DO_META_SORT_ADV + + return i_test; }