1 /*****************************************************************************
2 * sort.c : Playlist sorting functions
3 *****************************************************************************
4 * Copyright (C) 1999-2004 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 *****************************************************************************/
23 #include <stdlib.h> /* free(), strtol() */
24 #include <stdio.h> /* sprintf() */
25 #include <string.h> /* strerror() */
28 #include <vlc/input.h>
32 #include "vlc_playlist.h"
35 int playlist_ItemArraySort( playlist_t *p_playlist, int i_items,
36 playlist_item_t **pp_items, int i_mode,
42 * This function must be entered with the playlist lock !
44 * \param p_playlist the playlist
45 * \param p_node the node to sort
46 * \param i_mode: SORT_ID, SORT_TITLE, SORT_AUTHOR, SORT_ALBUM, SORT_RANDOM
47 * \param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order)
48 * \return VLC_SUCCESS on success
50 int playlist_NodeSort( playlist_t * p_playlist , playlist_item_t *p_node,
51 int i_mode, int i_type )
54 playlist_ItemArraySort( p_playlist,p_node->i_children,
55 p_node->pp_children, i_mode, i_type );
62 * Sort a node recursively.
64 * This function must be entered with the playlist lock !
66 * \param p_playlist the playlist
67 * \param p_node the node to sort
68 * \param i_mode: SORT_ID, SORT_TITLE, SORT_AUTHOR, SORT_ALBUM, SORT_RANDOM
69 * \param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order)
70 * \return VLC_SUCCESS on success
72 int playlist_RecursiveNodeSort( playlist_t *p_playlist, playlist_item_t *p_node,
73 int i_mode, int i_type )
77 playlist_NodeSort( p_playlist, p_node, i_mode, i_type );
78 for( i = 0 ; i< p_node->i_children; i++ )
80 if( p_node->pp_children[i]->i_children != -1 )
82 playlist_RecursiveNodeSort( p_playlist, p_node->pp_children[i],
92 int playlist_ItemArraySort( playlist_t *p_playlist, int i_items,
93 playlist_item_t **pp_items, int i_mode,
96 int i , i_small , i_position;
97 playlist_item_t *p_temp;
99 val.b_bool = VLC_TRUE;
101 if( i_mode == SORT_RANDOM )
103 for( i_position = 0; i_position < i_items ; i_position ++ )
108 i_new = rand() % (i_items - 1);
111 p_temp = pp_items[i_position];
112 pp_items[i_position] = pp_items[i_new];
113 pp_items[i_new] = p_temp;
119 for( i_position = 0; i_position < i_items -1 ; i_position ++ )
121 i_small = i_position;
122 for( i = i_position + 1 ; i< i_items ; i++)
126 if( i_mode == SORT_TITLE )
128 i_test = strcasecmp( pp_items[i]->p_input->psz_name,
129 pp_items[i_small]->p_input->psz_name );
131 else if( i_mode == SORT_TITLE_NUMERIC )
133 i_test = atoi( pp_items[i]->p_input->psz_name ) -
134 atoi( pp_items[i_small]->p_input->psz_name );
136 else if( i_mode == SORT_DURATION )
138 i_test = pp_items[i]->p_input->i_duration -
139 pp_items[i_small]->p_input->i_duration;
141 else if( i_mode == SORT_AUTHOR )
143 char *psz_a = pp_items[i]->p_input->p_meta->psz_artist;
144 char *psz_b = pp_items[i_small]->p_input->p_meta->psz_artist;
145 if( pp_items[i]->i_children == -1 &&
146 pp_items[i_small]->i_children >= 0 )
150 else if( pp_items[i]->i_children >= 0 &&
151 pp_items[i_small]->i_children == -1 )
156 else if( pp_items[i]->i_children >= 0 &&
157 pp_items[i_small]->i_children >= 0 )
159 i_test = strcasecmp( pp_items[i]->p_input->psz_name,
160 pp_items[i_small]->p_input->psz_name );
162 else if( psz_a == NULL && psz_b != NULL )
166 else if( psz_a != NULL && psz_b == NULL )
170 else if( psz_a == NULL && psz_b == NULL )
172 i_test = strcasecmp( pp_items[i]->p_input->psz_name,
173 pp_items[i_small]->p_input->psz_name );
177 i_test = strcmp( psz_b, psz_a );
180 else if( i_mode == SORT_ALBUM )
182 char *psz_a = pp_items[i]->p_input->p_meta->psz_album;
183 char *psz_b = pp_items[i_small]->p_input->p_meta->psz_album;
184 if( pp_items[i]->i_children == -1 &&
185 pp_items[i_small]->i_children >= 0 )
189 else if( pp_items[i]->i_children >= 0 &&
190 pp_items[i_small]->i_children == -1 )
195 else if( pp_items[i]->i_children >= 0 &&
196 pp_items[i_small]->i_children >= 0 )
198 i_test = strcasecmp( pp_items[i]->p_input->psz_name,
199 pp_items[i_small]->p_input->psz_name );
201 else if( psz_a == NULL && psz_b != NULL )
205 else if( psz_a != NULL && psz_b == NULL )
209 else if( psz_a == NULL && psz_b == NULL )
211 i_test = strcasecmp( pp_items[i]->p_input->psz_name,
212 pp_items[i_small]->p_input->psz_name );
216 i_test = strcmp( psz_b, psz_a );
219 else if( i_mode == SORT_TITLE_NODES_FIRST )
221 /* Alphabetic sort, all nodes first */
223 if( pp_items[i]->i_children == -1 &&
224 pp_items[i_small]->i_children >= 0 )
228 else if( pp_items[i]->i_children >= 0 &&
229 pp_items[i_small]->i_children == -1 )
235 i_test = strcasecmp( pp_items[i]->p_input->psz_name,
236 pp_items[i_small]->p_input->psz_name );
240 if( ( i_type == ORDER_NORMAL && i_test < 0 ) ||
241 ( i_type == ORDER_REVERSE && i_test > 0 ) )
246 p_temp = pp_items[i_position];
247 pp_items[i_position] = pp_items[i_small];
248 pp_items[i_small] = p_temp;
254 int playlist_NodeGroup( playlist_t * p_playlist , playlist_item_t *p_root,
255 playlist_item_t **pp_items,int i_item,
256 int i_mode, int i_type )
258 char *psz_search = NULL;
260 playlist_item_t **pp_nodes = NULL;
261 playlist_item_t *p_node;
264 for( i = 0; i< i_item ; i++ )
266 if( psz_search ) free( psz_search );
267 if( i_mode == SORT_TITLE )
269 psz_search = strdup( pp_items[i]->p_input->psz_name );
271 else if ( i_mode == SORT_AUTHOR )
273 psz_search = pp_items[i]->p_input->p_meta->psz_artist;
275 else if ( i_mode == SORT_ALBUM )
277 psz_search = pp_items[i]->p_input->p_meta->psz_album;
279 else if ( i_mode == SORT_GENRE )
281 psz_search = pp_items[i]->p_input->p_meta->psz_genre;
284 if( psz_search && !strcmp( psz_search, "" ) )
287 psz_search = strdup( _("Undefined") );
291 for( j = 0 ; j< i_nodes; j++ )
293 if( !strcasecmp( psz_search, pp_nodes[j]->p_input->psz_name ) )
295 playlist_NodeAppend( p_playlist, pp_items[i], pp_nodes[j] );
302 p_node = playlist_NodeCreate( p_playlist, psz_search, NULL );
303 INSERT_ELEM( pp_nodes, i_nodes, i_nodes, p_node );
304 playlist_NodeAppend( p_playlist, pp_items[i],p_node );
308 /* Now, sort the nodes by name */
309 playlist_ItemArraySort( p_playlist, i_nodes, pp_nodes, SORT_TITLE,
312 /* Now, sort each node and append it to the root node*/
313 for( i = 0 ; i< i_nodes ; i++ )
315 playlist_ItemArraySort( p_playlist, pp_nodes[i]->i_children,
316 pp_nodes[i]->pp_children, SORT_TITLE, i_type );
318 playlist_NodeAppend( p_playlist, pp_nodes[i], p_root );