sort.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * sort.c : Playlist sorting functions
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2007 the VideoLAN team
  5.  * $Id: dd477fbdf3a5ff6f0d077565fe335e12ad67db3e $
  6.  *
  7.  * Authors: Clément Stenac <zorglub@videolan.org>
  8.  *          Ilkka Ollakka <ileoo@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. #ifdef HAVE_CONFIG_H
  25. # include "config.h"
  26. #endif
  27. #include <vlc_common.h>
  28. #include "vlc_playlist.h"
  29. #include "playlist_internal.h"
  30. static int playlist_ItemArraySort( playlist_t *p_playlist, int i_items,
  31.                                    playlist_item_t **pp_items, int i_mode,
  32.                                    int i_type );
  33. static int playlist_cmp(const void *, const void *);
  34. /**
  35.  * Sort a node.
  36.  * This function must be entered with the playlist lock !
  37.  *
  38.  * param p_playlist the playlist
  39.  * param p_node the node to sort
  40.  * param i_mode: SORT_ID, SORT_TITLE, SORT_ARTIST, SORT_ALBUM, SORT_RANDOM
  41.  * param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order)
  42.  * return VLC_SUCCESS on success
  43.  */
  44. static int playlist_NodeSort( playlist_t * p_playlist , playlist_item_t *p_node,
  45.                               int i_mode, int i_type )
  46. {
  47.     playlist_ItemArraySort( p_playlist,p_node->i_children,
  48.                             p_node->pp_children, i_mode, i_type );
  49.     return VLC_SUCCESS;
  50. }
  51. /**
  52.  * Sort a node recursively
  53.  * param p_playlist the playlist
  54.  * param p_node the node to sort
  55.  * param i_mode: SORT_ID, SORT_TITLE, SORT_ARTIST, SORT_ALBUM, SORT_RANDOM
  56.  * param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order)
  57.  * return VLC_SUCCESS on success
  58.  */
  59. static int recursiveNodeSort( playlist_t *p_playlist, playlist_item_t *p_node,
  60.                               int i_mode, int i_type )
  61. {
  62.     int i;
  63.     /* Sort the current node */
  64.     playlist_NodeSort( p_playlist, p_node, i_mode, i_type );
  65.     /* And all the children */
  66.     for( i = 0 ; i< p_node->i_children; i++ )
  67.     {
  68.         if( p_node->pp_children[i]->i_children != -1 )
  69.         {
  70.             recursiveNodeSort( p_playlist, p_node->pp_children[i],
  71.                                i_mode, i_type );
  72.         }
  73.     }
  74.     return VLC_SUCCESS;
  75. }
  76. /**
  77.  * Sort a node recursively.
  78.  *
  79.  * This function must be entered with the playlist lock !
  80.  *
  81.  * param p_playlist the playlist
  82.  * param p_node the node to sort
  83.  * param i_mode: SORT_ID, SORT_TITLE, SORT_ARTIST, SORT_ALBUM, SORT_RANDOM
  84.  * param i_type: ORDER_NORMAL or ORDER_REVERSE (reversed order)
  85.  * return VLC_SUCCESS on success
  86.  */
  87. int playlist_RecursiveNodeSort( playlist_t *p_playlist, playlist_item_t *p_node,
  88.                                 int i_mode, int i_type )
  89. {
  90.     /* Ask the playlist to reset as we are changing the order */
  91.     pl_priv(p_playlist)->b_reset_currently_playing = true;
  92.     /* Do the real job recursively */
  93.     return recursiveNodeSort( p_playlist, p_node, i_mode, i_type );
  94. }
  95. static int sort_mode = 0;
  96. static int sort_type = 0;
  97. static vlc_mutex_t sort_lock = VLC_STATIC_MUTEX;
  98. static int playlist_ItemArraySort( playlist_t *p_playlist, int i_items,
  99.                                    playlist_item_t **pp_items, int i_mode,
  100.                                    int i_type )
  101. {
  102.     int i_position;
  103.     playlist_item_t *p_temp;
  104.     (void)p_playlist; // a bit surprising we don't need p_playlist!
  105.     if( i_mode == SORT_RANDOM )
  106.     {
  107.         for( i_position = 0; i_position < i_items ; i_position ++ )
  108.         {
  109.             int i_new;
  110.             if( i_items > 1 )
  111.                 i_new = rand() % (i_items - 1);
  112.             else
  113.                 i_new = 0;
  114.             p_temp = pp_items[i_position];
  115.             pp_items[i_position] = pp_items[i_new];
  116.             pp_items[i_new] = p_temp;
  117.         }
  118.         return VLC_SUCCESS;
  119.     }
  120.     vlc_mutex_lock( &sort_lock );
  121.     sort_mode = i_mode;
  122.     sort_type = i_type;
  123.     qsort(pp_items,i_items,sizeof(pp_items[0]),playlist_cmp);
  124.     vlc_mutex_unlock( &sort_lock );
  125.     return VLC_SUCCESS;
  126. }
  127. static int playlist_cmp(const void *first, const void *second)
  128. {
  129. #define META_STRCASECMP_NAME( ) { 
  130.     char *psz_i = input_item_GetTitleFbName( (*(playlist_item_t **)first)->p_input ); 
  131.     char *psz_ismall = input_item_GetTitleFbName( (*(playlist_item_t **)second)->p_input ); 
  132.     if( psz_i != NULL && psz_ismall != NULL ) i_test = strcasecmp( psz_i, psz_ismall ); 
  133.     else if ( psz_i == NULL && psz_ismall != NULL ) i_test = 1; 
  134.     else if ( psz_ismall == NULL && psz_i != NULL ) i_test = -1; 
  135.     else i_test = 0; 
  136.     free( psz_i ); 
  137.     free( psz_ismall ); 
  138. }
  139. #define DO_META_SORT_ADV( node, integer ) { 
  140.     char *psz_a = input_item_GetMeta( (*(playlist_item_t **)first)->p_input, vlc_meta_##node ); 
  141.     char *psz_b = input_item_GetMeta( (*(playlist_item_t **)second)->p_input, vlc_meta_##node ); 
  142.     /* Nodes go first */ 
  143.     if( (*(playlist_item_t **)first)->i_children == -1 && (*(playlist_item_t **)second)->i_children >= 0 ) 
  144.         i_test = 1;
  145.     else if( (*(playlist_item_t **)first)->i_children >= 0 &&
  146.              (*(playlist_item_t **)second)->i_children == -1 ) 
  147.        i_test = -1; 
  148.     /* Both are nodes, sort by name */ 
  149.     else if( (*(playlist_item_t **)first)->i_children >= 0 && 
  150.                (*(playlist_item_t **)second)->i_children >= 0 ) 
  151.     { 
  152.         META_STRCASECMP_NAME( ) 
  153.     } 
  154.     /* Both are items */ 
  155.     else if( psz_a == NULL && psz_b != NULL ) 
  156.         i_test = 1; 
  157.     else if( psz_a != NULL && psz_b == NULL ) 
  158.         i_test = -1;
  159.     /* No meta, sort by name */ 
  160.     else if( psz_a == NULL && psz_b == NULL ) 
  161.     { 
  162.         META_STRCASECMP_NAME( ); 
  163.     } 
  164.     else 
  165.     { 
  166.         if( !integer ) i_test = strcasecmp( psz_a, psz_b ); 
  167.         else           i_test = atoi( psz_a ) - atoi( psz_b ); 
  168.     } 
  169.     free( psz_a ); 
  170.     free( psz_b ); 
  171. }
  172. #define DO_META_SORT( node ) DO_META_SORT_ADV( node, false )
  173.     int i_test = 0;
  174.     if( sort_mode == SORT_TITLE )
  175.     {
  176.         META_STRCASECMP_NAME( );
  177.     }
  178.     else if( sort_mode == SORT_TITLE_NUMERIC )
  179.     {
  180.         char *psz_i = input_item_GetTitleFbName(
  181.                                 (*(playlist_item_t **)first)->p_input );
  182.         char *psz_ismall = input_item_GetTitleFbName(
  183.                                 (*(playlist_item_t **)second)->p_input );
  184.         i_test = atoi( psz_i ) - atoi( psz_ismall );
  185.         free( psz_i );
  186.         free( psz_ismall );
  187.     }
  188.     else if( sort_mode == SORT_DURATION )
  189.     {
  190.         i_test = input_item_GetDuration( (*(playlist_item_t **)first)->p_input ) -
  191.                  input_item_GetDuration( (*(playlist_item_t **)second)->p_input );
  192.     }
  193.     else if( sort_mode == SORT_ARTIST )
  194.     {
  195.         DO_META_SORT( Artist );
  196.         /* sort by artist, album, tracknumber */
  197.         if( i_test == 0 )
  198.             DO_META_SORT( Album );
  199.         if( i_test == 0 )
  200.             DO_META_SORT_ADV( TrackNumber, true );
  201.     }
  202.     else if( sort_mode == SORT_GENRE )
  203.     {
  204.         DO_META_SORT( Genre );
  205.     }
  206.     else if( sort_mode == SORT_ALBUM )
  207.     {
  208.         DO_META_SORT( Album );
  209.         /* Sort by tracknumber if albums are the same */
  210.         if( i_test == 0 )
  211.             DO_META_SORT_ADV( TrackNumber, true );
  212.     }
  213.     else if( sort_mode == SORT_TRACK_NUMBER )
  214.     {
  215.         DO_META_SORT_ADV( TrackNumber, true );
  216.     }
  217.     else if( sort_mode == SORT_DESCRIPTION )
  218.     {
  219.         DO_META_SORT( Description );
  220.     }
  221.     else if( sort_mode == SORT_ID )
  222.     {
  223.         i_test = (*(playlist_item_t **)first)->i_id - (*(playlist_item_t **)second)->i_id;
  224.     }
  225.     else if( sort_mode == SORT_TITLE_NODES_FIRST )
  226.     {
  227.         /* Alphabetic sort, all nodes first */
  228.         if( (*(playlist_item_t **)first)->i_children == -1 &&
  229.             (*(playlist_item_t **)second)->i_children >= 0 )
  230.         {
  231.             i_test = 1;
  232.         }
  233.         else if( (*(playlist_item_t **)first)->i_children >= 0 &&
  234.                  (*(playlist_item_t **)second)->i_children == -1 )
  235.         {
  236.             i_test = -1;
  237.         }
  238.         else
  239.         {
  240.             META_STRCASECMP_NAME();
  241.         }
  242.     }
  243.     else if( sort_mode == SORT_URI )
  244.     {
  245.         char *psz_i = input_item_GetURI( (*(playlist_item_t **)first)->p_input );
  246.         char *psz_ismall =
  247.                 input_item_GetURI( (*(playlist_item_t **)second)->p_input );
  248.         i_test = strcasecmp( psz_i, psz_ismall );
  249.         free( psz_i );
  250.         free( psz_ismall );
  251.     }
  252.     if ( sort_type == ORDER_REVERSE )
  253.         i_test = i_test * -1;
  254. #undef DO_META_SORT
  255. #undef DO_META_SORT_ADV
  256.     return i_test;
  257. }