From: JP Dinger Date: Fri, 29 May 2009 22:14:24 +0000 (+0200) Subject: playlist/sort.c: remove globals, replace with pointers to generated stubs. X-Git-Tag: 1.1.0-ff~5712 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=88acaceec1898f65126be3e000de2b73ab3209f9;p=vlc playlist/sort.c: remove globals, replace with pointers to generated stubs. --- diff --git a/include/vlc_playlist.h b/include/vlc_playlist.h index d8de71caa0..098b3f2038 100644 --- a/include/vlc_playlist.h +++ b/include/vlc_playlist.h @@ -16,9 +16,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #ifndef VLC_PLAYLIST_H_ @@ -192,22 +192,36 @@ struct playlist_add_t int i_item; /**< Playist id of the playlist_item_t */ }; +/* A bit of macro magic to generate an enum out of the following list, + * and later, to generate a list of static functions out of the same list. + * There is also SORT_RANDOM, which is always last and handled specially. + */ +#define VLC_DEFINE_SORT_FUNCTIONS \ + DEF( SORT_ID )\ + DEF( SORT_TITLE )\ + DEF( SORT_TITLE_NODES_FIRST )\ + DEF( SORT_ARTIST )\ + DEF( SORT_GENRE )\ + DEF( SORT_DURATION )\ + DEF( SORT_TITLE_NUMERIC )\ + DEF( SORT_ALBUM )\ + DEF( SORT_TRACK_NUMBER )\ + DEF( SORT_DESCRIPTION )\ + DEF( SORT_RATING )\ + DEF( SORT_URI ) + +#define DEF( s ) s, enum { - SORT_ID = 0, - SORT_TITLE = 1, - SORT_TITLE_NODES_FIRST = 2, - SORT_ARTIST = 3, - SORT_GENRE = 4, - SORT_RANDOM = 5, - SORT_DURATION = 6, - SORT_TITLE_NUMERIC = 7, - SORT_ALBUM = 8, - SORT_TRACK_NUMBER = 9, - SORT_DESCRIPTION = 10, - SORT_RATING = 11, - SORT_URI = 12, + VLC_DEFINE_SORT_FUNCTIONS + SORT_RANDOM, + NUM_SORT_FNS=SORT_RANDOM }; +#undef DEF +#ifndef VLC_INTERNAL_PLAYLIST_SORT_FUNCTIONS +#undef VLC_DEFINE_SORT_FUNCTIONS +#endif + enum { ORDER_NORMAL = 0, diff --git a/src/playlist/sort.c b/src/playlist/sort.c index 4003b0d840..ad1e861e7a 100644 --- a/src/playlist/sort.c +++ b/src/playlist/sort.c @@ -18,38 +18,20 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include +#define VLC_INTERNAL_PLAYLIST_SORT_FUNCTIONS #include "vlc_playlist.h" #include "playlist_internal.h" -static void playlist_ItemArraySort( int i_items, playlist_item_t **pp_items, - int i_mode, int i_type ); -static int playlist_cmp( const void *, const void * ); - -/* Comparison functions */ -static int playlist_cmp_album( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_artist( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_desc( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_duration( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_genre( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_id( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_rating( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_title( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_title_nodes_first( const playlist_item_t *, - const playlist_item_t *); -static int playlist_cmp_title_num( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_track_num( const playlist_item_t *, const playlist_item_t *); -static int playlist_cmp_uri( const playlist_item_t *, const playlist_item_t *); - /* General comparison functions */ /** * Compare two items using their title or name @@ -123,6 +105,62 @@ static inline int meta_sort( const playlist_item_t *first, return i_ret; } +/* Comparison functions */ + +/** + * Return the comparison function appropriate for the SORT_* and ORDER_* + * arguments given, or NULL for SORT_RANDOM. + * @param i_mode: a SORT_* enum indicating the field to sort on + * @param i_type: ORDER_NORMAL or ORDER_REVERSE + * @return function pointer, or NULL for SORT_RANDOM or invalid input + */ +typedef int (*sortfn_t)(const void *,const void *); +static const sortfn_t sorting_fns[NUM_SORT_FNS][2]; +static inline sortfn_t find_sorting_fn( unsigned i_mode, unsigned i_type ) +{ + if( i_mode>=NUM_SORT_FNS || i_type>1 ) + return 0; + return sorting_fns[i_mode][i_type]; +} + +/** + * Sort an array of items recursively + * @param i_items: number of items + * @param pp_items: the array of items + * @param i_mode: a SORT_* enum indicating the field to sort on + * @param i_type: ORDER_NORMAL or ORDER_REVERSE + * @return nothing + */ +static inline +void playlist_ItemArraySort( unsigned i_items, playlist_item_t **pp_items, + unsigned i_mode, unsigned i_type ) +{ + sortfn_t sortfn = find_sorting_fn(i_mode, i_type); + + if( sortfn ) + { + qsort( pp_items, i_items, sizeof( pp_items[0] ), sortfn ); + } + else /* Randomise */ + { + int i_position; + playlist_item_t *p_temp; + + for( i_position = 0; i_position < i_items ; i_position++ ) + { + int i_new; + + if( i_items > 1 ) + i_new = rand() % (i_items - 1); + else + i_new = 0; + p_temp = pp_items[i_position]; + pp_items[i_position] = pp_items[i_new]; + pp_items[i_new] = p_temp; + } + } +} + /** * Sort a node recursively. @@ -172,115 +210,20 @@ int playlist_RecursiveNodeSort( playlist_t *p_playlist, playlist_item_t *p_node, } -static int (*sort_function)(const playlist_item_t *, const playlist_item_t *); -static int sort_order = 1; - - -/** - * Sort an array of items recursively - * @param i_items: number of items - * @param pp_items: the array of items - * @param i_mode: the criterias for the comparisons - * @param i_type: ORDER_NORMAL or ORDER_REVERSE - * @return nothing +/* This is the stuff the sorting functions are made of. The proto_## + * functions are wrapped in cmp_a_## and cmp_d_## functions that do + * void * to const playlist_item_t * casting and dereferencing and + * cmp_d_## inverts the result, too. proto_## are static inline, + * cmp_[ad]_## are merely inline as they're the target of pointers. + * + * In any case, each SORT_## constant (except SORT_RANDOM) must have + * a matching SORTFN( )-declared function here. */ -static void playlist_ItemArraySort( int i_items, playlist_item_t **pp_items, - int i_mode, int i_type ) -{ - int i_position; - playlist_item_t *p_temp; - - /* Random sort */ - if( i_mode == SORT_RANDOM ) - { - for( i_position = 0; i_position < i_items ; i_position++ ) - { - int i_new; - - if( i_items > 1 ) - i_new = rand() % (i_items - 1); - else - i_new = 0; - p_temp = pp_items[i_position]; - pp_items[i_position] = pp_items[i_new]; - pp_items[i_new] = p_temp; - } - } - else - { - /* Choose the funtion to compare two items */ - switch( i_mode ) - { - case SORT_ALBUM: - sort_function = playlist_cmp_album; - break; - case SORT_ARTIST: - sort_function = playlist_cmp_artist; - break; - case SORT_DESCRIPTION: - sort_function = playlist_cmp_desc; - break; - case SORT_DURATION: - sort_function = playlist_cmp_duration; - break; - case SORT_GENRE: - sort_function = playlist_cmp_genre; - break; - case SORT_ID: - sort_function = playlist_cmp_id; - break; - case SORT_TITLE: - sort_function = playlist_cmp_title; - break; - case SORT_TITLE_NODES_FIRST: - sort_function = playlist_cmp_title_nodes_first; - break; - case SORT_TITLE_NUMERIC: - sort_function = playlist_cmp_title_num; - break; - case SORT_TRACK_NUMBER: - sort_function = playlist_cmp_track_num; - break; - case SORT_RATING: - sort_function = playlist_cmp_rating; - break; - case SORT_URI: - sort_function = playlist_cmp_uri; - break; - default: - assert(0); - } - sort_order = i_type == ORDER_REVERSE ? -1 : 1; - qsort( pp_items, i_items, sizeof( pp_items[0] ), playlist_cmp ); - } -} +#define SORTFN( SORT, first, second ) static inline int proto_##SORT \ + ( const playlist_item_t *first, const playlist_item_t *second ) -/** - * Wrapper around playlist_cmp_* function - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp( const void *first, const void *second ) -{ - if( sort_order == -1 ) - return -1 * sort_function( *(playlist_item_t **)first, - *(playlist_item_t **)second ); - else - return sort_function( *(playlist_item_t **)first, - *(playlist_item_t **)second ); -} - - -/** - * Compare two items according to the title - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_album( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_ALBUM, first, second ) { int i_ret = meta_sort( first, second, vlc_meta_Album, false ); /* Items came from the same album: compare the track numbers */ @@ -290,112 +233,48 @@ static int playlist_cmp_album( const playlist_item_t *first, return i_ret; } - -/** - * Compare two items according to the artist - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_artist( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_ARTIST, first, second ) { int i_ret = meta_sort( first, second, vlc_meta_Artist, false ); /* Items came from the same artist: compare the albums */ if( i_ret == 0 ) - i_ret = playlist_cmp_album( first, second ); + i_ret = proto_SORT_ALBUM( first, second ); return i_ret; } - -/** - * Compare two items according to the description - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_desc( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_DESCRIPTION, first, second ) { return meta_sort( first, second, vlc_meta_Description, false ); } - -/** - * Compare two items according to the duration - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_duration( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_DURATION, first, second ) { return input_item_GetDuration( first->p_input ) - input_item_GetDuration( second->p_input ); } - -/** - * Compare two items according to the genre - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_genre( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_GENRE, first, second ) { return meta_sort( first, second, vlc_meta_Genre, false ); } - -/** - * Compare two items according to the ID - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_id( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_ID, first, second ) { return first->i_id - second->i_id; } - -/** - * Compare two items according to the rating - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_rating( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_RATING, first, second ) { return meta_sort( first, second, vlc_meta_Rating, true ); } - -/** - * Compare two items according to the title - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_title( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_TITLE, first, second ) { return meta_strcasecmp_title( first, second ); } - -/** - * Compare two items according to the title, with the nodes first in the list - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_title_nodes_first( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_TITLE_NODES_FIRST, first, second ) { /* If first is a node but not second */ if( first->i_children == -1 && second->i_children >= 0 ) @@ -408,15 +287,7 @@ static int playlist_cmp_title_nodes_first( const playlist_item_t *first, return meta_strcasecmp_title( first, second ); } - -/** - * Compare two item according to the title as a numeric value - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_title_num( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_TITLE_NUMERIC, first, second ) { int i_ret; char *psz_first = input_item_GetTitleFbName( first->p_input ); @@ -436,28 +307,12 @@ static int playlist_cmp_title_num( const playlist_item_t *first, return i_ret; } - -/** - * Compare two item according to the track number - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_track_num( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_TRACK_NUMBER, first, second ) { return meta_sort( first, second, vlc_meta_TrackNumber, true ); } - -/** - * Compare two item according to the URI - * @param first: the first item - * @param second: the second item - * @return -1, 0 or 1 like strcmp - */ -static int playlist_cmp_uri( const playlist_item_t *first, - const playlist_item_t *second ) +SORTFN( SORT_URI, first, second ) { int i_ret; char *psz_first = input_item_GetURI( first->p_input ); @@ -477,4 +332,32 @@ static int playlist_cmp_uri( const playlist_item_t *first, return i_ret; } +#undef SORTFN + +/* Generate stubs around the proto_## sorting functions, ascending and + * descending both. Preprocessor magic up ahead. Brace yourself. + */ + +#ifndef VLC_DEFINE_SORT_FUNCTIONS +#error Where is VLC_DEFINE_SORT_FUNCTIONS? +#endif + +#define DEF( s ) \ + static int cmp_a_##s(const void *l,const void *r) \ + { return proto_##s(*(const playlist_item_t *const *)l, \ + *(const playlist_item_t *const *)r); } \ + static int cmp_d_##s(const void *l,const void *r) \ + { return -1*proto_##s(*(const playlist_item_t * const *)l, \ + *(const playlist_item_t * const *)r); } + + VLC_DEFINE_SORT_FUNCTIONS + +#undef DEF + +/* And populate an array with the addresses */ + +static const sortfn_t sorting_fns[NUM_SORT_FNS][2] = +#define DEF( a ) { cmp_a_##a, cmp_d_##a }, +{ VLC_DEFINE_SORT_FUNCTIONS }; +#undef DEF