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 *****************************************************************************/
28 #include "vlc_playlist.h"
29 #include "playlist_internal.h"
32 static int playlist_ItemArraySort( playlist_t
*p_playlist
, int i_items
,
33 playlist_item_t
**pp_items
, int i_mode
,
38 * This function must be entered with the playlist lock !
40 * \param p_playlist the playlist
41 * \param p_node the node to sort
42 * \param i_mode: SORT_ID, SORT_TITLE, SORT_ARTIST, SORT_ALBUM, SORT_RANDOM
43 * \param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order)
44 * \return VLC_SUCCESS on success
46 static int playlist_NodeSort( playlist_t
* p_playlist
, playlist_item_t
*p_node
,
47 int i_mode
, int i_type
)
49 playlist_ItemArraySort( p_playlist
,p_node
->i_children
,
50 p_node
->pp_children
, i_mode
, i_type
);
55 * Sort a node recursively.
57 * This function must be entered with the playlist lock !
59 * \param p_playlist the playlist
60 * \param p_node the node to sort
61 * \param i_mode: SORT_ID, SORT_TITLE, SORT_ARTIST, SORT_ALBUM, SORT_RANDOM
62 * \param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order)
63 * \return VLC_SUCCESS on success
65 int playlist_RecursiveNodeSort( playlist_t
*p_playlist
, playlist_item_t
*p_node
,
66 int i_mode
, int i_type
)
69 playlist_NodeSort( p_playlist
, p_node
, i_mode
, i_type
);
70 for( i
= 0 ; i
< p_node
->i_children
; i
++ )
72 if( p_node
->pp_children
[i
]->i_children
!= -1 )
74 playlist_RecursiveNodeSort( p_playlist
, p_node
->pp_children
[i
],
82 static int playlist_ItemArraySort( playlist_t
*p_playlist
, int i_items
,
83 playlist_item_t
**pp_items
, int i_mode
,
86 int i
, i_small
, i_position
;
87 playlist_item_t
*p_temp
;
89 val
.b_bool
= VLC_TRUE
;
91 (void)p_playlist
; // a bit surprising we don't need p_playlist!
93 if( i_mode
== SORT_RANDOM
)
95 for( i_position
= 0; i_position
< i_items
; i_position
++ )
100 i_new
= rand() % (i_items
- 1);
103 p_temp
= pp_items
[i_position
];
104 pp_items
[i_position
] = pp_items
[i_new
];
105 pp_items
[i_new
] = p_temp
;
111 #define META_STRCASECMP_NAME( i, i_small ) { \
112 char *psz_i = input_item_GetName( pp_items[i]->p_input ); \
113 char *psz_ismall = input_item_GetName( pp_items[i_small]->p_input ); \
114 i_test = strcasecmp( psz_i, psz_ismall ); \
116 free( psz_ismall ); \
120 #define DO_META_SORT( node ) { \
121 char *psz_a = input_item_GetMeta( pp_items[i]->p_input, vlc_meta_##node ); \
122 char *psz_b = input_item_GetMeta( pp_items[i_small]->p_input, vlc_meta_##node ); \
123 /* Nodes go first */ \
124 if( pp_items[i]->i_children == -1 && pp_items[i_small]->i_children >= 0 ) \
126 else if( pp_items[i]->i_children >= 0 &&\
127 pp_items[i_small]->i_children == -1 ) \
129 /* Both are nodes, sort by name */ \
130 else if( pp_items[i]->i_children >= 0 && \
131 pp_items[i_small]->i_children >= 0 ) \
133 META_STRCASECMP_NAME( i, i_small ) \
135 /* Both are items */ \
136 else if( psz_a == NULL && psz_b != NULL ) \
138 else if( psz_a != NULL && psz_b == NULL ) \
140 /* No meta, sort by name */ \
141 else if( psz_a == NULL && psz_b == NULL ) \
143 META_STRCASECMP_NAME( i, i_small ); \
147 i_test = strcmp( psz_b, psz_a ); \
153 for( i_position
= 0; i_position
< i_items
-1 ; i_position
++ )
155 i_small
= i_position
;
156 for( i
= i_position
+ 1 ; i
< i_items
; i
++)
160 if( i_mode
== SORT_TITLE
)
162 META_STRCASECMP_NAME( i
, i_small
);
164 else if( i_mode
== SORT_TITLE_NUMERIC
)
166 char *psz_i
= input_item_GetName( pp_items
[i
]->p_input
);
168 input_item_GetName( pp_items
[i_small
]->p_input
);
169 i_test
= atoi( psz_i
) - atoi( psz_ismall
);
173 else if( i_mode
== SORT_DURATION
)
175 i_test
= input_item_GetDuration( pp_items
[i
]->p_input
) -
176 input_item_GetDuration( pp_items
[i_small
]->p_input
);
178 else if( i_mode
== SORT_ARTIST
)
180 DO_META_SORT( Artist
);
182 else if( i_mode
== SORT_ALBUM
)
184 DO_META_SORT( Album
);
186 else if( i_mode
== SORT_TITLE_NODES_FIRST
)
188 /* Alphabetic sort, all nodes first */
190 if( pp_items
[i
]->i_children
== -1 &&
191 pp_items
[i_small
]->i_children
>= 0 )
195 else if( pp_items
[i
]->i_children
>= 0 &&
196 pp_items
[i_small
]->i_children
== -1 )
202 i_test
= strcasecmp( pp_items
[i
]->p_input
->psz_name
,
203 pp_items
[i_small
]->p_input
->psz_name
);
207 if( ( i_type
== ORDER_NORMAL
&& i_test
< 0 ) ||
208 ( i_type
== ORDER_REVERSE
&& i_test
> 0 ) )
213 p_temp
= pp_items
[i_position
];
214 pp_items
[i_position
] = pp_items
[i_small
];
215 pp_items
[i_small
] = p_temp
;