1 /*****************************************************************************
2 * sort.c : Playlist sorting functions
3 *****************************************************************************
4 * Copyright (C) 1999-2007 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #include "vlc_playlist.h"
25 #include "playlist_internal.h"
28 static int playlist_ItemArraySort( playlist_t *p_playlist, int i_items,
29 playlist_item_t **pp_items, int i_mode,
34 * This function must be entered with the playlist lock !
36 * \param p_playlist the playlist
37 * \param p_node the node to sort
38 * \param i_mode: SORT_ID, SORT_TITLE, SORT_ARTIST, SORT_ALBUM, SORT_RANDOM
39 * \param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order)
40 * \return VLC_SUCCESS on success
42 static int playlist_NodeSort( playlist_t * p_playlist , playlist_item_t *p_node,
43 int i_mode, int i_type )
45 playlist_ItemArraySort( p_playlist,p_node->i_children,
46 p_node->pp_children, i_mode, i_type );
51 * Sort a node recursively.
53 * This function must be entered with the playlist lock !
55 * \param p_playlist the playlist
56 * \param p_node the node to sort
57 * \param i_mode: SORT_ID, SORT_TITLE, SORT_ARTIST, SORT_ALBUM, SORT_RANDOM
58 * \param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order)
59 * \return VLC_SUCCESS on success
61 int playlist_RecursiveNodeSort( playlist_t *p_playlist, playlist_item_t *p_node,
62 int i_mode, int i_type )
65 playlist_NodeSort( p_playlist, p_node, i_mode, i_type );
66 for( i = 0 ; i< p_node->i_children; i++ )
68 if( p_node->pp_children[i]->i_children != -1 )
70 playlist_RecursiveNodeSort( p_playlist, p_node->pp_children[i],
78 static int playlist_ItemArraySort( playlist_t *p_playlist, int i_items,
79 playlist_item_t **pp_items, int i_mode,
82 int i , i_small , i_position;
83 playlist_item_t *p_temp;
85 val.b_bool = VLC_TRUE;
87 (void)p_playlist; // a bit surprising we don't need p_playlist!
89 if( i_mode == SORT_RANDOM )
91 for( i_position = 0; i_position < i_items ; i_position ++ )
96 i_new = rand() % (i_items - 1);
99 p_temp = pp_items[i_position];
100 pp_items[i_position] = pp_items[i_new];
101 pp_items[i_new] = p_temp;
107 #define META_STRCASECMP_NAME( i, i_small ) { \
108 char *psz_i = input_item_GetName( pp_items[i]->p_input ); \
109 char *psz_ismall = input_item_GetName( pp_items[i_small]->p_input ); \
110 i_test = strcasecmp( psz_i, psz_ismall ); \
112 free( psz_ismall ); \
116 #define DO_META_SORT( node ) { \
117 char *psz_a = input_item_GetMeta( pp_items[i]->p_input, vlc_meta_##node ); \
118 char *psz_b = input_item_GetMeta( pp_items[i_small]->p_input, vlc_meta_##node ); \
119 /* Nodes go first */ \
120 if( pp_items[i]->i_children == -1 && pp_items[i_small]->i_children >= 0 ) \
122 else if( pp_items[i]->i_children >= 0 &&\
123 pp_items[i_small]->i_children == -1 ) \
125 /* Both are nodes, sort by name */ \
126 else if( pp_items[i]->i_children >= 0 && \
127 pp_items[i_small]->i_children >= 0 ) \
129 META_STRCASECMP_NAME( i, i_small ) \
131 /* Both are items */ \
132 else if( psz_a == NULL && psz_b != NULL ) \
134 else if( psz_a != NULL && psz_b == NULL ) \
136 /* No meta, sort by name */ \
137 else if( psz_a == NULL && psz_b == NULL ) \
139 META_STRCASECMP_NAME( i, i_small ); \
143 i_test = strcmp( psz_b, psz_a ); \
149 for( i_position = 0; i_position < i_items -1 ; i_position ++ )
151 i_small = i_position;
152 for( i = i_position + 1 ; i< i_items ; i++)
156 if( i_mode == SORT_TITLE )
158 META_STRCASECMP_NAME( i, i_small );
160 else if( i_mode == SORT_TITLE_NUMERIC )
162 char *psz_i = input_item_GetName( pp_items[i]->p_input );
164 input_item_GetName( pp_items[i_small]->p_input );
165 i_test = atoi( psz_i ) - atoi( psz_ismall );
169 else if( i_mode == SORT_DURATION )
171 i_test = input_item_GetDuration( pp_items[i]->p_input ) -
172 input_item_GetDuration( pp_items[i_small]->p_input );
174 else if( i_mode == SORT_ARTIST )
176 DO_META_SORT( Artist );
178 else if( i_mode == SORT_ALBUM )
180 DO_META_SORT( Album );
182 else if( i_mode == SORT_TITLE_NODES_FIRST )
184 /* Alphabetic sort, all nodes first */
186 if( pp_items[i]->i_children == -1 &&
187 pp_items[i_small]->i_children >= 0 )
191 else if( pp_items[i]->i_children >= 0 &&
192 pp_items[i_small]->i_children == -1 )
198 i_test = strcasecmp( pp_items[i]->p_input->psz_name,
199 pp_items[i_small]->p_input->psz_name );
203 if( ( i_type == ORDER_NORMAL && i_test < 0 ) ||
204 ( i_type == ORDER_REVERSE && i_test > 0 ) )
209 p_temp = pp_items[i_position];
210 pp_items[i_position] = pp_items[i_small];
211 pp_items[i_small] = p_temp;