X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fncurses.c;h=64ba96bf17d89e8d2e80226477acb08b61ee8a95;hb=566b63e7c7ad0570c36e226eabd6ea75ae0227e4;hp=40e0f97665ffd1fcbb42ee2f7c7fee820ef693b2;hpb=58cdead84a3c9a78a78eef1c545a0201ab206a15;p=vlc diff --git a/modules/gui/ncurses.c b/modules/gui/ncurses.c index 40e0f97665..64ba96bf17 100644 --- a/modules/gui/ncurses.c +++ b/modules/gui/ncurses.c @@ -1,7 +1,7 @@ /***************************************************************************** * ncurses.c : NCurses plugin for vlc ***************************************************************************** - * Copyright (C) 2001-2004 VideoLAN + * Copyright (C) 2001-2006 the VideoLAN team * $Id$ * * Authors: Sam Hocevar @@ -21,12 +21,13 @@ * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ +#define _GNU_SOURCE #include /* malloc(), free() */ #include #include /* ENOMEM */ @@ -36,9 +37,12 @@ #include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include #ifdef HAVE_SYS_STAT_H # include @@ -75,7 +79,19 @@ static void Eject ( intf_thread_t * ); static int HandleKey ( intf_thread_t *, int ); static void Redraw ( intf_thread_t *, time_t * ); + +static playlist_item_t *PlaylistGetRoot( intf_thread_t * ); +static void PlaylistRebuild( intf_thread_t * ); +static void PlaylistAddNode( intf_thread_t *, playlist_item_t *, int, const char *); +static void PlaylistDestroy( intf_thread_t * ); +static int PlaylistChanged( vlc_object_t *, const char *, vlc_value_t, + vlc_value_t, void * ); +static inline vlc_bool_t PlaylistIsPlaying( intf_thread_t *, + playlist_item_t * ); +static void FindIndex ( intf_thread_t * ); static void SearchPlaylist ( intf_thread_t *, char * ); +static int SubSearchPlaylist( intf_thread_t *, char *, int, int ); + static void ManageSlider ( intf_thread_t * ); static void ReadDir ( intf_thread_t * ); @@ -85,12 +101,15 @@ static void ReadDir ( intf_thread_t * ); #define BROWSE_TEXT N_("Filebrowser starting point") #define BROWSE_LONGTEXT N_( \ - "This option allows you to specify directory the ncurses filebrowser" \ + "This option allows you to specify the directory the ncurses filebrowser " \ "will show you initially.") vlc_module_begin(); - set_description( _("ncurses interface") ); + set_shortname( "Ncurses" ); + set_description( _("Ncurses interface") ); set_capability( "interface", 10 ); + set_category( CAT_INTERFACE ); + set_subcategory( SUBCAT_INTERFACE_MAIN ); set_callbacks( Open, Close ); add_shortcut( "curses" ); add_directory( "browse-dir", NULL, NULL, BROWSE_TEXT, BROWSE_LONGTEXT, VLC_FALSE ); @@ -110,11 +129,21 @@ enum BOX_OPEN, BOX_BROWSE }; +enum +{ + VIEW_CATEGORY, + VIEW_ONELEVEL +}; struct dir_entry_t { vlc_bool_t b_file; char *psz_path; }; +struct pl_item_t +{ + playlist_item_t *p_item; + char *psz_display; +}; struct intf_sys_t { playlist_t *p_playlist; @@ -133,6 +162,8 @@ struct intf_sys_t int i_box_plidx; /* Playlist index */ int b_box_plidx_follow; + playlist_item_t *p_plnode; /* Playlist node */ + int i_box_bidx; /* browser index */ int b_box_cleared; @@ -143,13 +174,20 @@ struct intf_sys_t int i_before_search; char *psz_open_chain; - + char psz_partial_keys[7]; + char *psz_current_dir; int i_dir_entries; struct dir_entry_t **pp_dir_entries; + vlc_bool_t b_show_hidden_files; + + int i_current_view; /* playlist view */ + struct pl_item_t **pp_plist; + int i_plist_entries; + vlc_bool_t b_need_update; /* for playlist view */ }; -static void DrawBox( WINDOW *win, int y, int x, int h, int w, char *title ); +static void DrawBox( WINDOW *win, int y, int x, int h, int w, const char *title ); static void DrawLine( WINDOW *win, int y, int x, int w ); static void DrawEmptyLine( WINDOW *win, int y, int x, int w ); @@ -175,7 +213,10 @@ static int Open( vlc_object_t *p_this ) p_sys->b_box_plidx_follow = VLC_TRUE; p_sys->b_box_cleared = VLC_FALSE; p_sys->i_box_plidx = 0; - p_sys->p_sub = msg_Subscribe( p_intf ); + p_sys->p_plnode = NULL; + p_sys->i_box_bidx = 0; + p_sys->p_sub = msg_Subscribe( p_intf, MSG_QUEUE_NORMAL ); + memset( p_sys->psz_partial_keys, 0, sizeof( p_sys->psz_partial_keys ) ); /* Initialize the curses library */ p_sys->w = initscr(); @@ -197,7 +238,13 @@ static int Open( vlc_object_t *p_this ) /* Set quiet mode */ val.i_int = -1; - var_Set( p_intf->p_vlc, "verbose", val ); + var_Set( p_intf->p_libvlc, "verbose", val ); + + /* Set defaul playlist view */ + p_sys->i_current_view = VIEW_CATEGORY; + p_sys->pp_plist = NULL; + p_sys->i_plist_entries = 0; + p_sys->b_need_update = VLC_FALSE; /* Initialize search chain */ p_sys->psz_search_chain = (char *)malloc( SEARCH_CHAIN_SIZE + 1 ); @@ -206,23 +253,24 @@ static int Open( vlc_object_t *p_this ) /* Initialize open chain */ p_sys->psz_open_chain = (char *)malloc( OPEN_CHAIN_SIZE + 1 ); - + /* Initialize browser options */ var_Create( p_intf, "browse-dir", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_intf, "browse-dir", &val); - + if( val.psz_string && *val.psz_string ) { - p_sys->psz_current_dir = strdup( val.psz_string); + p_sys->psz_current_dir = strdup( val.psz_string ); free( val.psz_string ); } else { - p_sys->psz_current_dir = strdup( p_intf->p_vlc->psz_homedir ); + p_sys->psz_current_dir = strdup( p_intf->p_libvlc->psz_homedir ); } - + p_sys->i_dir_entries = 0; - p_sys->pp_dir_entries = NULL; + p_sys->pp_dir_entries = NULL; + p_sys->b_show_hidden_files = VLC_FALSE; ReadDir( p_intf ); return VLC_SUCCESS; @@ -237,6 +285,13 @@ static void Close( vlc_object_t *p_this ) intf_sys_t *p_sys = p_intf->p_sys; int i; + var_DelCallback( p_sys->p_playlist, "intf-change", PlaylistChanged, + p_intf ); + var_DelCallback( p_sys->p_playlist, "item-append", PlaylistChanged, + p_intf ); + + PlaylistDestroy( p_intf ); + for( i = 0; i < p_sys->i_dir_entries; i++ ) { struct dir_entry_t *p_dir_entry = p_sys->pp_dir_entries[i]; @@ -245,7 +300,7 @@ static void Close( vlc_object_t *p_this ) if( p_dir_entry ) free( p_dir_entry ); } p_sys->pp_dir_entries = NULL; - + if( p_sys->psz_current_dir ) free( p_sys->psz_current_dir ); if( p_sys->psz_search_chain ) free( p_sys->psz_search_chain ); if( p_sys->psz_old_search ) free( p_sys->psz_old_search ); @@ -284,14 +339,22 @@ static void Run( intf_thread_t *p_intf ) */ t_last_refresh = ( time( 0 ) - 1); - while( !p_intf->b_die ) + while( !intf_ShouldDie( p_intf ) ) { msleep( INTF_IDLE_SLEEP ); /* Update the input */ if( p_sys->p_playlist == NULL ) { - p_sys->p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); + p_sys->p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( p_sys->p_playlist ) + { + var_AddCallback( p_sys->p_playlist, "intf-change", + PlaylistChanged, p_intf ); + var_AddCallback( p_sys->p_playlist, "item-append", + PlaylistChanged, p_intf ); + } } if( p_sys->p_playlist ) { @@ -317,18 +380,17 @@ static void Run( intf_thread_t *p_intf ) vlc_mutex_unlock( &p_sys->p_playlist->object_lock ); } - if( p_sys->b_box_plidx_follow && p_sys->p_playlist->i_index >= 0 ) + if( p_sys->b_box_plidx_follow && p_sys->p_playlist->status.p_item ) { - p_sys->i_box_plidx = p_sys->p_playlist->i_index; + FindIndex( p_intf ); } - - while( ( i_key = getch()) != -1 ) + while( ( i_key = getch() ) != -1 ) { /* * HandleKey returns 1 if the screen needs to be redrawn */ - if ( HandleKey( p_intf, i_key ) ) + if( HandleKey( p_intf, i_key ) ) { Redraw( p_intf, &t_last_refresh ); } @@ -344,9 +406,9 @@ static void Run( intf_thread_t *p_intf ) /* * redraw the screen every second */ - if ( (time(0) - t_last_refresh) >= 1 ) + if( (time(0) - t_last_refresh) >= 1 ) { - ManageSlider ( p_intf ); + ManageSlider( p_intf ); Redraw( p_intf, &t_last_refresh ); } } @@ -354,6 +416,52 @@ static void Run( intf_thread_t *p_intf ) /* following functions are local */ +static char *KeyToUTF8( int i_key, char *psz_part ) +{ + char *psz_utf8, *psz; + int len = strlen( psz_part ); + if( len == 6 ) + { + /* overflow error - should not happen */ + memset( psz_part, 0, 6 ); + return NULL; + } + + psz_part[len] = (char)i_key; + + psz_utf8 = FromLocaleDup( psz_part ); + + /* Ugly check for incomplete bytes sequences + * (in case of non-UTF8 multibyte local encoding) */ + for( psz = psz_utf8; *psz; psz++ ) + if( ( *psz == '?' ) && ( *psz_utf8 != '?' ) ) + { + /* incomplete bytes sequence detected + * (VLC core inserted dummy question marks) */ + free( psz_utf8 ); + return NULL; + } + + /* Check for incomplete UTF8 bytes sequence */ + if( EnsureUTF8( psz_utf8 ) == NULL ) + { + free( psz_utf8 ); + return NULL; + } + + memset( psz_part, 0, 6 ); + return psz_utf8; +} + +static inline int RemoveLastUTF8Entity( char *psz, int len ) +{ + while( len && ( (psz[--len] & 0xc0) == 0x80 ) ); + /* UTF8 continuation byte */ + + psz[len] = '\0'; + return len; +} + static int HandleKey( intf_thread_t *p_intf, int i_key ) { intf_sys_t *p_sys = p_intf->p_sys; @@ -362,6 +470,7 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) if( p_sys->i_box_type == BOX_PLAYLIST && p_sys->p_playlist ) { int b_ret = VLC_TRUE; + vlc_bool_t b_box_plidx_follow = VLC_FALSE; switch( i_key ) { @@ -385,10 +494,30 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) /* Playlist sort */ case 'o': - playlist_Sort( p_sys->p_playlist, SORT_TITLE, ORDER_NORMAL ); + playlist_RecursiveNodeSort( p_sys->p_playlist, + PlaylistGetRoot( p_intf ), + SORT_TITLE_NODES_FIRST, ORDER_NORMAL ); + p_sys->b_need_update = VLC_TRUE; return 1; case 'O': - playlist_Sort( p_sys->p_playlist, SORT_TITLE, ORDER_REVERSE ); + playlist_RecursiveNodeSort( p_sys->p_playlist, + PlaylistGetRoot( p_intf ), + SORT_TITLE_NODES_FIRST, ORDER_REVERSE ); + p_sys->b_need_update = VLC_TRUE; + return 1; + + /* Playlist view */ + case 'v': + switch( p_sys->i_current_view ) + { + case VIEW_CATEGORY: + p_sys->i_current_view = VIEW_ONELEVEL; + break; + default: + p_sys->i_current_view = VIEW_CATEGORY; + } + //p_sys->b_need_update = VLC_TRUE; + PlaylistRebuild( p_intf ); return 1; /* Playlist navigation */ @@ -396,7 +525,7 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) p_sys->i_box_plidx = 0; break; case KEY_END: - p_sys->i_box_plidx = p_sys->p_playlist->i_size - 1; + p_sys->i_box_plidx = p_sys->p_playlist->items.i_size - 1; break; case KEY_UP: p_sys->i_box_plidx--; @@ -414,19 +543,44 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) case KEY_BACKSPACE: case KEY_DC: { - int i_item = p_sys->p_playlist->i_index; + playlist_t *p_playlist = p_sys->p_playlist; + playlist_item_t *p_item; - playlist_Delete( p_sys->p_playlist, p_sys->i_box_plidx ); - if( i_item < p_sys->p_playlist->i_size && i_item != p_sys->p_playlist->i_index ) + vlc_mutex_lock( &p_playlist->object_lock ); + p_item = p_sys->pp_plist[p_sys->i_box_plidx]->p_item; + if( p_item->i_children == -1 ) { - playlist_Goto( p_sys->p_playlist, i_item ); + playlist_DeleteFromInput( p_playlist, + p_item->p_input->i_id, VLC_TRUE ); } + else + { + playlist_NodeDelete( p_playlist, p_item, + VLC_TRUE , VLC_FALSE ); + } + vlc_mutex_unlock( &p_playlist->object_lock ); + p_sys->b_need_update = VLC_TRUE; + break; } case KEY_ENTER: case 0x0d: - playlist_Goto( p_sys->p_playlist, p_sys->i_box_plidx ); + if( p_sys->pp_plist[p_sys->i_box_plidx]->p_item->i_children + == -1 ) + { + playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY, + VLC_TRUE, NULL, + p_sys->pp_plist[p_sys->i_box_plidx]->p_item ); + } + else + { + playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY, + VLC_TRUE, + p_sys->pp_plist[p_sys->i_box_plidx]->p_item, + NULL ); + } + b_box_plidx_follow = VLC_TRUE; break; default: b_ret = VLC_FALSE; @@ -435,76 +589,85 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) if( b_ret ) { - if( p_sys->i_box_plidx >= p_sys->p_playlist->i_size ) p_sys->i_box_plidx = p_sys->p_playlist->i_size - 1; + int i_max = p_sys->i_plist_entries; + if( p_sys->i_box_plidx >= i_max ) p_sys->i_box_plidx = i_max - 1; if( p_sys->i_box_plidx < 0 ) p_sys->i_box_plidx = 0; - if( p_sys->i_box_plidx == p_sys->p_playlist->i_index ) - p_sys->b_box_plidx_follow = VLC_TRUE; - else - p_sys->b_box_plidx_follow = VLC_FALSE; + if( PlaylistIsPlaying( p_intf, + p_sys->pp_plist[p_sys->i_box_plidx]->p_item ) ) + b_box_plidx_follow = VLC_TRUE; + p_sys->b_box_plidx_follow = b_box_plidx_follow; return 1; } } if( p_sys->i_box_type == BOX_BROWSE ) { + vlc_bool_t b_ret = VLC_TRUE; /* Browser navigation */ switch( i_key ) { case KEY_HOME: - p_sys->i_box_plidx = 0; + p_sys->i_box_bidx = 0; break; case KEY_END: - p_sys->i_box_plidx = p_sys->i_dir_entries - 1; + p_sys->i_box_bidx = p_sys->i_dir_entries - 1; break; case KEY_UP: - p_sys->i_box_plidx--; + p_sys->i_box_bidx--; break; case KEY_DOWN: - p_sys->i_box_plidx++; + p_sys->i_box_bidx++; break; case KEY_PPAGE: - p_sys->i_box_plidx -= p_sys->i_box_lines; + p_sys->i_box_bidx -= p_sys->i_box_lines; break; case KEY_NPAGE: - p_sys->i_box_plidx += p_sys->i_box_lines; + p_sys->i_box_bidx += p_sys->i_box_lines; + break; + case '.': /* Toggle show hidden files */ + p_sys->b_show_hidden_files = ( p_sys->b_show_hidden_files == + VLC_TRUE ? VLC_FALSE : VLC_TRUE ); + ReadDir( p_intf ); break; case KEY_ENTER: case 0x0d: - if( p_sys->pp_dir_entries[p_sys->i_box_plidx]->b_file ) + case ' ': + if( p_sys->pp_dir_entries[p_sys->i_box_bidx]->b_file || i_key == ' ' ) { int i_size_entry = strlen( p_sys->psz_current_dir ) + - strlen( p_sys->pp_dir_entries[p_sys->i_box_plidx]->psz_path ) + 2; + strlen( p_sys->pp_dir_entries[p_sys->i_box_bidx]->psz_path ) + 2; char *psz_uri = (char *)malloc( sizeof(char)*i_size_entry); - sprintf( psz_uri, "%s/%s", p_sys->psz_current_dir, p_sys->pp_dir_entries[p_sys->i_box_plidx]->psz_path ); + sprintf( psz_uri, "%s/%s", p_sys->psz_current_dir, p_sys->pp_dir_entries[p_sys->i_box_bidx]->psz_path ); + /* XXX playlist_Add( p_sys->p_playlist, psz_uri, psz_uri, PLAYLIST_APPEND, PLAYLIST_END ); + */ p_sys->i_box_type = BOX_PLAYLIST; free( psz_uri ); } else { int i_size_entry = strlen( p_sys->psz_current_dir ) + - strlen( p_sys->pp_dir_entries[p_sys->i_box_plidx]->psz_path ) + 2; + strlen( p_sys->pp_dir_entries[p_sys->i_box_bidx]->psz_path ) + 2; char *psz_uri = (char *)malloc( sizeof(char)*i_size_entry); - sprintf( psz_uri, "%s/%s", p_sys->psz_current_dir, p_sys->pp_dir_entries[p_sys->i_box_plidx]->psz_path ); - + sprintf( psz_uri, "%s/%s", p_sys->psz_current_dir, p_sys->pp_dir_entries[p_sys->i_box_bidx]->psz_path ); + p_sys->psz_current_dir = strdup( psz_uri ); ReadDir( p_intf ); free( psz_uri ); } break; default: + b_ret = VLC_FALSE; break; - - if( p_sys->i_box_plidx >= p_sys->i_dir_entries ) p_sys->i_box_plidx = p_sys->i_dir_entries - 1; - if( p_sys->i_box_plidx < 0 ) p_sys->i_box_plidx = 0; - if( p_sys->i_box_plidx == p_sys->i_dir_entries ) - p_sys->b_box_plidx_follow = VLC_TRUE; - else - p_sys->b_box_plidx_follow = VLC_FALSE; + } + if( b_ret ) + { + if( p_sys->i_box_bidx >= p_sys->i_dir_entries ) p_sys->i_box_bidx = p_sys->i_dir_entries - 1; + if( p_sys->i_box_bidx < 0 ) p_sys->i_box_bidx = 0; return 1; } } @@ -548,21 +711,21 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) { case KEY_HOME: p_sys->f_slider = 0; - ManageSlider ( p_intf ); + ManageSlider( p_intf ); return 1; case KEY_END: p_sys->f_slider = 99.9; - ManageSlider ( p_intf ); + ManageSlider( p_intf ); return 1; case KEY_UP: p_sys->f_slider += 5.0; if( p_sys->f_slider >= 99.0 ) p_sys->f_slider = 99.0; - ManageSlider ( p_intf ); + ManageSlider( p_intf ); return 1; case KEY_DOWN: p_sys->f_slider -= 5.0; if( p_sys->f_slider < 0.0 ) p_sys->f_slider = 0.0; - ManageSlider ( p_intf ); + ManageSlider( p_intf ); return 1; default: @@ -595,18 +758,23 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) p_sys->i_box_type = BOX_PLAYLIST; return 1; case KEY_BACKSPACE: - if( i_chain_len > 0 ) - { - p_sys->psz_search_chain[ i_chain_len - 1 ] = '\0'; - } + RemoveLastUTF8Entity( p_sys->psz_search_chain, i_chain_len ); break; default: - if( i_chain_len < SEARCH_CHAIN_SIZE ) + { + char *psz_utf8 = KeyToUTF8( i_key, p_sys->psz_partial_keys ); + + if( psz_utf8 != NULL ) { - p_sys->psz_search_chain[ i_chain_len++ ] = i_key; - p_sys->psz_search_chain[ i_chain_len ] = 0; + if( i_chain_len + strlen( psz_utf8 ) < SEARCH_CHAIN_SIZE ) + { + strcpy( p_sys->psz_search_chain + i_chain_len, + psz_utf8 ); + } + free( psz_utf8 ); } break; + } } if( p_sys->psz_old_search ) { @@ -618,8 +786,7 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) } else if( p_sys->i_box_type == BOX_OPEN && p_sys->psz_open_chain ) { - int i_chain_len; - i_chain_len = strlen( p_sys->psz_open_chain ); + int i_chain_len = strlen( p_sys->psz_open_chain ); playlist_t *p_playlist = p_sys->p_playlist; switch( i_key ) @@ -631,9 +798,11 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) case 0x0d: if( p_playlist && i_chain_len > 0 ) { + /* playlist_Add( p_playlist, p_sys->psz_open_chain, p_sys->psz_open_chain, PLAYLIST_GO|PLAYLIST_APPEND, PLAYLIST_END ); + */ p_sys->b_box_plidx_follow = VLC_TRUE; } p_sys->i_box_type = BOX_PLAYLIST; @@ -642,18 +811,23 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) p_sys->i_box_type = BOX_PLAYLIST; return 1; case KEY_BACKSPACE: - if( i_chain_len > 0 ) - { - p_sys->psz_open_chain[ i_chain_len - 1 ] = '\0'; - } + RemoveLastUTF8Entity( p_sys->psz_open_chain, i_chain_len ); break; default: - if( i_chain_len < OPEN_CHAIN_SIZE ) + { + char *psz_utf8 = KeyToUTF8( i_key, p_sys->psz_partial_keys ); + + if( psz_utf8 != NULL ) { - p_sys->psz_open_chain[ i_chain_len++ ] = i_key; - p_sys->psz_open_chain[ i_chain_len ] = 0; + if( i_chain_len + strlen( psz_utf8 ) < OPEN_CHAIN_SIZE ) + { + strcpy( p_sys->psz_open_chain + i_chain_len, + psz_utf8 ); + } + free( psz_utf8 ); } break; + } } return 1; } @@ -665,7 +839,7 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) case 'q': case 'Q': case 0x1b: /* Esc */ - p_intf->p_vlc->b_die = VLC_TRUE; + vlc_object_kill( p_intf->p_libvlc ); return 0; /* Box switching */ @@ -731,28 +905,43 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) case KEY_RIGHT: p_sys->f_slider += 1.0; if( p_sys->f_slider > 99.9 ) p_sys->f_slider = 99.9; - ManageSlider ( p_intf ); + ManageSlider( p_intf ); return 1; case KEY_LEFT: p_sys->f_slider -= 1.0; if( p_sys->f_slider < 0.0 ) p_sys->f_slider = 0.0; - ManageSlider ( p_intf ); + ManageSlider( p_intf ); return 1; /* Common control */ case 'f': { - vout_thread_t *p_vout; if( p_intf->p_sys->p_input ) { + vout_thread_t *p_vout; p_vout = vlc_object_find( p_intf->p_sys->p_input, VLC_OBJECT_VOUT, FIND_CHILD ); if( p_vout ) { - p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; + var_Get( p_vout, "fullscreen", &val ); + val.b_bool = !val.b_bool; + var_Set( p_vout, "fullscreen", val ); vlc_object_release( p_vout ); } + else + { + playlist_t *p_playlist; + p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( p_playlist ) + { + var_Get( p_playlist, "fullscreen", &val ); + val.b_bool = !val.b_bool; + var_Set( p_playlist, "fullscreen", val ); + vlc_object_release( p_playlist ); + } + } } return 0; } @@ -842,7 +1031,7 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) } } -static void ManageSlider ( intf_thread_t *p_intf ) +static void ManageSlider( intf_thread_t *p_intf ) { intf_sys_t *p_sys = p_intf->p_sys; input_thread_t *p_input = p_sys->p_input; @@ -875,15 +1064,15 @@ static void ManageSlider ( intf_thread_t *p_intf ) static void SearchPlaylist( intf_thread_t *p_intf, char *psz_searchstring ) { - bool b_ok = false; - int i_current; + int i_max; int i_first = 0 ; int i_item = -1; intf_sys_t *p_sys = p_intf->p_sys; - playlist_t *p_playlist = p_sys->p_playlist; if( p_sys->i_before_search >= 0 ) + { i_first = p_sys->i_before_search; + } if( ( ! psz_searchstring ) || strlen( psz_searchstring ) <= 0 ) { @@ -891,38 +1080,36 @@ static void SearchPlaylist( intf_thread_t *p_intf, char *psz_searchstring ) return; } - for( i_current = i_first + 1; i_current < p_playlist->i_size; - i_current++ ) + i_max = p_sys->i_plist_entries; + + i_item = SubSearchPlaylist( p_intf, psz_searchstring, i_first + 1, i_max ); + if( i_item < 0 ) { - if( strcasestr( p_playlist->pp_items[i_current]->input.psz_name, - psz_searchstring ) != NULL - || strcasestr( p_playlist->pp_items[i_current]->input.psz_uri, - psz_searchstring ) != NULL ) - { - i_item = i_current; - b_ok = true; - break; - } + i_item = SubSearchPlaylist( p_intf, psz_searchstring, 0, i_first ); } - if( !b_ok ) + + if( i_item < 0 || i_item >= i_max ) return; + + p_sys->i_box_plidx = i_item; +} + +static int SubSearchPlaylist( intf_thread_t *p_intf, char *psz_searchstring, + int i_start, int i_stop ) +{ + intf_sys_t *p_sys = p_intf->p_sys; + int i, i_item = -1; + + for( i = i_start + 1; i < i_stop; i++ ) { - for( i_current = 0; i_current < i_first; i_current++ ) + if( strcasestr( p_sys->pp_plist[i]->psz_display, + psz_searchstring ) != NULL ) { - if( strcasestr( p_playlist->pp_items[i_current]->input.psz_name, - psz_searchstring ) != NULL - || strcasestr( p_playlist->pp_items[i_current]->input.psz_uri, - psz_searchstring ) != NULL ) - { - i_item = i_current; - b_ok = true; - break; - } + i_item = i; + break; } } - if( i_item < 0 || i_item >= p_playlist->i_size ) return; - - p_sys->i_box_plidx = i_item; + return i_item; } @@ -932,11 +1119,11 @@ static void mvnprintw( int y, int x, int w, const char *p_fmt, ... ) char *p_buf = NULL; int i_len; - va_start ( vl_args, p_fmt ); - vasprintf ( &p_buf, p_fmt, vl_args ); - va_end ( vl_args ); + va_start( vl_args, p_fmt ); + vasprintf( &p_buf, p_fmt, vl_args ); + va_end( vl_args ); - if ( p_buf == NULL ) + if( p_buf == NULL ) { return; } @@ -944,6 +1131,7 @@ static void mvnprintw( int y, int x, int w, const char *p_fmt, ... ) { if( ( i_len = strlen( p_buf ) ) > w ) { + char *psz_local; int i_cut = i_len - w; int x1 = i_len/2 - i_cut/2; int x2 = x1 + i_cut; @@ -959,11 +1147,15 @@ static void mvnprintw( int y, int x, int w, const char *p_fmt, ... ) p_buf[w/2 ] = '.'; p_buf[w/2+1] = '.'; } - mvprintw( y, x, "%s", p_buf ); + psz_local = ToLocale( p_buf ); + mvprintw( y, x, "%s", psz_local ); + LocaleFree( p_buf ); } else { - mvprintw( y, x, "%s", p_buf ); + char *psz_local = ToLocale( p_buf ); + mvprintw( y, x, "%s", psz_local ); + LocaleFree( p_buf ); mvhline( y, x + i_len, ' ', w - i_len ); } } @@ -980,9 +1172,9 @@ static void MainBoxWrite( intf_thread_t *p_intf, int l, int x, const char *p_fmt return; } - va_start ( vl_args, p_fmt ); - vasprintf ( &p_buf, p_fmt, vl_args ); - va_end ( vl_args ); + va_start( vl_args, p_fmt ); + vasprintf( &p_buf, p_fmt, vl_args ); + va_end( vl_args ); if( p_buf == NULL ) { @@ -992,7 +1184,7 @@ static void MainBoxWrite( intf_thread_t *p_intf, int l, int x, const char *p_fmt mvnprintw( p_sys->i_box_y + l - p_sys->i_box_start, x, COLS - x - 1, "%s", p_buf ); } -static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) +static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh ) { intf_sys_t *p_sys = p_intf->p_sys; input_thread_t *p_input = p_sys->p_input; @@ -1000,12 +1192,12 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) int h; int y_end; - //clear(); + clear(); /* Title */ - attrset ( A_REVERSE ); + attrset( A_REVERSE ); mvnprintw( y, 0, COLS, "VLC media player" " (ncurses interface) [ h for help ]" ); - attroff ( A_REVERSE ); + attroff( A_REVERSE ); y += 2; /* Infos */ @@ -1017,7 +1209,8 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) vlc_value_t val_list; /* Source */ - mvnprintw( y++, 0, COLS, " Source : %s", p_input->psz_source ); + mvnprintw( y++, 0, COLS, " Source : %s", + input_GetItem(p_input)->psz_uri ); /* State */ var_Get( p_input, "state", &val ); @@ -1025,6 +1218,14 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) { mvnprintw( y++, 0, COLS, " State : Playing" ); } + else if( val.i_int == OPENING_S ) + { + mvnprintw( y++, 0, COLS, " State : Openning/Connecting" ); + } + else if( val.i_int == BUFFERING_S ) + { + mvnprintw( y++, 0, COLS, " State : Buffering" ); + } else if( val.i_int == PAUSE_S ) { mvnprintw( y++, 0, COLS, " State : Paused" ); @@ -1074,7 +1275,7 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) } else { - y++; + y += 2; } } else @@ -1136,6 +1337,12 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) MainBoxWrite( p_intf, l++, 1, " Delete an entry" ); MainBoxWrite( p_intf, l++, 1, "" ); + MainBoxWrite( p_intf, l++, 1, "[Filebrowser]" ); + MainBoxWrite( p_intf, l++, 1, " Add the selected file to the playlist" ); + MainBoxWrite( p_intf, l++, 1, " Add the selected directory to the playlist" ); + MainBoxWrite( p_intf, l++, 1, " . Show/Hide hidden files" ); + MainBoxWrite( p_intf, l++, 1, "" ); + MainBoxWrite( p_intf, l++, 1, "[Boxes]" ); MainBoxWrite( p_intf, l++, 1, " , Navigate through the box line by line" ); MainBoxWrite( p_intf, l++, 1, " , Navigate through the box page by page" ); @@ -1172,20 +1379,20 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) if( p_input ) { int i,j; - vlc_mutex_lock( &p_input->p_item->lock ); - for ( i = 0; i < p_input->p_item->i_categories; i++ ) + vlc_mutex_lock( &input_GetItem(p_input)->lock ); + for( i = 0; i < input_GetItem(p_input)->i_categories; i++ ) { - info_category_t *p_category = p_input->p_item->pp_categories[i]; + info_category_t *p_category = input_GetItem(p_input)->pp_categories[i]; if( y >= y_end ) break; MainBoxWrite( p_intf, l++, 1, " [%s]", p_category->psz_name ); - for ( j = 0; j < p_category->i_infos; j++ ) + for( j = 0; j < p_category->i_infos; j++ ) { info_t *p_info = p_category->pp_infos[j]; if( y >= y_end ) break; MainBoxWrite( p_intf, l++, 1, " %s: %s", p_info->psz_name, p_info->psz_value ); } } - vlc_mutex_unlock( &p_input->p_item->lock ); + vlc_mutex_unlock( &input_GetItem(p_input)->lock ); } else { @@ -1246,22 +1453,22 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) } else if( p_sys->i_box_type == BOX_BROWSE ) { - /* Playlist box */ + /* Filebrowser box */ int i_start, i_stop; int i_item; DrawBox( p_sys->w, y++, 0, h, COLS, " Browse " ); - if( p_sys->i_box_plidx >= p_sys->i_dir_entries ) p_sys->i_box_plidx = p_sys->i_dir_entries - 1; - if( p_sys->i_box_plidx < 0 ) p_sys->i_box_plidx = 0; + if( p_sys->i_box_bidx >= p_sys->i_dir_entries ) p_sys->i_box_plidx = p_sys->i_dir_entries - 1; + if( p_sys->i_box_bidx < 0 ) p_sys->i_box_bidx = 0; - if( p_sys->i_box_plidx < (h - 2)/2 ) + if( p_sys->i_box_bidx < (h - 2)/2 ) { i_start = 0; i_stop = h - 2; } - else if( p_sys->i_dir_entries - p_sys->i_box_plidx > (h - 2)/2 ) + else if( p_sys->i_dir_entries - p_sys->i_box_bidx > (h - 2)/2 ) { - i_start = p_sys->i_box_plidx - (h - 2)/2; + i_start = p_sys->i_box_bidx - (h - 2)/2; i_stop = i_start + h - 2; } else @@ -1280,18 +1487,18 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) for( i_item = i_start; i_item < i_stop; i_item++ ) { - vlc_bool_t b_selected = ( p_sys->i_box_plidx == i_item ); + vlc_bool_t b_selected = ( p_sys->i_box_bidx == i_item ); if( y >= y_end ) break; if( b_selected ) { attrset( A_REVERSE ); } - mvnprintw( y++, 1, COLS - 2, "%c %s", p_sys->pp_dir_entries[i_item]->b_file == VLC_TRUE ? '-' : '+', + mvnprintw( y++, 1, COLS - 2, " %c %s", p_sys->pp_dir_entries[i_item]->b_file == VLC_TRUE ? ' ' : '+', p_sys->pp_dir_entries[i_item]->psz_path ); if( b_selected ) { - attroff ( A_REVERSE ); + attroff( A_REVERSE ); } } @@ -1301,69 +1508,80 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) p_sys->i_box_type == BOX_OPEN ) && p_sys->p_playlist ) { /* Playlist box */ - playlist_t *p_playlist = p_sys->p_playlist; - int i_start, i_stop; + int i_start, i_stop, i_max = p_sys->i_plist_entries; int i_item; - DrawBox( p_sys->w, y++, 0, h, COLS, " Playlist " ); + char *psz_title; + + switch( p_sys->i_current_view ) + { + case VIEW_ONELEVEL: + psz_title = strdup( " Playlist (All, one level) " ); + break; + case VIEW_CATEGORY: + psz_title = strdup( " Playlist (By category) " ); + break; + default: + psz_title = strdup( " Playlist (Manually added) " ); + } + + DrawBox( p_sys->w, y++, 0, h, COLS, psz_title ); - if( p_sys->i_box_plidx >= p_playlist->i_size ) p_sys->i_box_plidx = p_playlist->i_size - 1; + if( p_sys->b_need_update || p_sys->pp_plist == NULL ) + { + PlaylistRebuild( p_intf ); + } + if( p_sys->b_box_plidx_follow ) + { + FindIndex( p_intf ); + } + + if( p_sys->i_box_plidx < 0 ) p_sys->i_box_plidx = 0; if( p_sys->i_box_plidx < 0 ) p_sys->i_box_plidx = 0; + if( p_sys->i_box_plidx >= i_max ) p_sys->i_box_plidx = i_max - 1; if( p_sys->i_box_plidx < (h - 2)/2 ) { i_start = 0; i_stop = h - 2; } - else if( p_playlist->i_size - p_sys->i_box_plidx > (h - 2)/2 ) + else if( i_max - p_sys->i_box_plidx > (h - 2)/2 ) { i_start = p_sys->i_box_plidx - (h - 2)/2; i_stop = i_start + h - 2; } else { - i_stop = p_playlist->i_size; - i_start = p_playlist->i_size - (h - 2); + i_stop = i_max; + i_start = i_max - (h - 2); } if( i_start < 0 ) { i_start = 0; } - if( i_stop > p_playlist->i_size ) + if( i_stop > i_max ) { - i_stop = p_playlist->i_size; + i_stop = i_max; } for( i_item = i_start; i_item < i_stop; i_item++ ) { vlc_bool_t b_selected = ( p_sys->i_box_plidx == i_item ); - int c = p_playlist->i_index == i_item ? '>' : ' '; + int c = ( PlaylistIsPlaying( p_intf, + p_sys->pp_plist[i_item]->p_item ) ) ? '>' : ' '; if( y >= y_end ) break; if( b_selected ) { attrset( A_REVERSE ); } - if( !strcmp( p_playlist->pp_items[i_item]->input.psz_name, - p_playlist->pp_items[i_item]->input.psz_uri ) ) - { - mvnprintw( y++, 1, COLS - 2, "%c %d - '%s'", - c, - i_item, - p_playlist->pp_items[i_item]->input.psz_uri ); - } - else - { - mvnprintw( y++, 1, COLS - 2, "%c %d - '%s' (%s)", - c, - i_item, - p_playlist->pp_items[i_item]->input.psz_uri, - p_playlist->pp_items[i_item]->input.psz_name ); - } + mvnprintw( y++, 1, COLS - 2, "%c%s", c, + p_sys->pp_plist[i_item]->psz_display ); if( b_selected ) { - attroff ( A_REVERSE ); + attroff( A_REVERSE ); } } + } else { @@ -1405,7 +1623,155 @@ static void Redraw ( intf_thread_t *p_intf, time_t *t_last_refresh ) *t_last_refresh = time( 0 ); } -static void Eject ( intf_thread_t *p_intf ) +static playlist_item_t *PlaylistGetRoot( intf_thread_t *p_intf ) +{ + intf_sys_t *p_sys = p_intf->p_sys; + playlist_t *p_playlist = p_sys->p_playlist; + + if( p_playlist == NULL ) + { + return NULL; + } + + switch( p_sys->i_current_view ) + { + case VIEW_CATEGORY: + return p_playlist->p_root_category; + default: + return p_playlist->p_root_onelevel; + } +} + +static void PlaylistRebuild( intf_thread_t *p_intf ) +{ + intf_sys_t *p_sys = p_intf->p_sys; + playlist_t *p_playlist = p_sys->p_playlist; + + if( p_playlist == NULL ) + { + return; + } + + vlc_mutex_lock( &p_playlist->object_lock ); + + /* First clear the old one */ + PlaylistDestroy( p_intf ); + + /* Build the new one */ + PlaylistAddNode( p_intf, PlaylistGetRoot( p_intf ), 0, "" ); + + p_sys->b_need_update = VLC_FALSE; + + vlc_mutex_unlock( &p_playlist->object_lock ); +} + +static void PlaylistAddNode( intf_thread_t *p_intf, playlist_item_t *p_node, + int i, const char *c ) +{ + intf_sys_t *p_sys = p_intf->p_sys; + playlist_item_t *p_child; + char *psz_tmp; + int k; + + psz_tmp = (char *)malloc( strlen( c ) + 4 ); + if( psz_tmp == NULL ) return; + for( k = 0; k < p_node->i_children; k++ ) + { + struct pl_item_t *p_pl_item; + char *buff; + int i_size; + + p_child = p_node->pp_children[k]; + i_size = strlen( c ) + strlen( p_child->p_input->psz_name ) + 4; + buff = (char *)malloc( sizeof( char ) * i_size ); + p_pl_item = (struct pl_item_t *)malloc( sizeof( struct pl_item_t ) ); + if( p_pl_item == NULL || buff == NULL ) return; + + if( strlen( c ) ) + { + sprintf( buff, "%s%c-%s", c, k == p_node->i_children - 1 ? + '`' : '|', p_child->p_input->psz_name ); + } + else + { + sprintf( buff, " %s", p_child->p_input->psz_name ); + } + p_pl_item->psz_display = strdup( buff ); + p_pl_item->p_item = p_child; + INSERT_ELEM( p_sys->pp_plist, p_sys->i_plist_entries, + p_sys->i_plist_entries, p_pl_item ); + free( buff ); + i++; + + if( p_child->i_children > 0 ) + { + sprintf( psz_tmp, "%s%c ", c, + k == p_node->i_children - 1 ? ' ' : '|' ); + PlaylistAddNode( p_intf, p_child, i, + strlen( c ) ? psz_tmp : " " ); + } + } + free( psz_tmp ); +} + +static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable, + vlc_value_t oval, vlc_value_t nval, void *param ) +{ + intf_thread_t *p_intf = (intf_thread_t *)param; + p_intf->p_sys->b_need_update = VLC_TRUE; + return VLC_SUCCESS; +} + +/* Playlist suxx */ +static inline vlc_bool_t PlaylistIsPlaying( intf_thread_t *p_intf, + playlist_item_t *p_item ) +{ + playlist_item_t *p_played_item = p_intf->p_sys->p_playlist->status.p_item; + return( p_item != NULL && p_played_item != NULL && + p_item->p_input != NULL && p_played_item->p_input != NULL && + p_item->p_input->i_id == p_played_item->p_input->i_id ); +} + +static void FindIndex( intf_thread_t *p_intf ) +{ + intf_sys_t *p_sys = p_intf->p_sys; + int i; + + if( p_sys->i_box_plidx < p_sys->i_plist_entries && + p_sys->i_box_plidx >= 0 && + PlaylistIsPlaying( p_intf, + p_sys->pp_plist[p_sys->i_box_plidx]->p_item ) ) + { + return; + } + + for( i = 0; i < p_sys->i_plist_entries; i++ ) + { + if( PlaylistIsPlaying( p_intf, p_sys->pp_plist[i]->p_item ) ) + { + p_sys->i_box_plidx = i; + break; + } + } +} + +static void PlaylistDestroy( intf_thread_t *p_intf ) +{ + intf_sys_t *p_sys = p_intf->p_sys; + int i; + + for( i = 0; i < p_sys->i_plist_entries; i++ ) + { + struct pl_item_t *p_pl_item = p_sys->pp_plist[i]; + free( p_pl_item->psz_display ); + REMOVE_ELEM( p_sys->pp_plist, p_sys->i_plist_entries, i ); + free( p_pl_item ); + } + p_sys->pp_plist = NULL; + p_sys->i_plist_entries = 0; +} + +static void Eject( intf_thread_t *p_intf ) { char *psz_device = NULL, *psz_parser, *psz_name; @@ -1425,14 +1791,14 @@ static void Eject ( intf_thread_t *p_intf ) vlc_mutex_lock( &p_playlist->object_lock ); - if( p_playlist->i_index < 0 ) + if( p_playlist->status.p_item == NULL ) { vlc_mutex_unlock( &p_playlist->object_lock ); vlc_object_release( p_playlist ); return; } - psz_name = p_playlist->pp_items[ p_playlist->i_index ]->input.psz_name; + psz_name = p_playlist->status.p_item->p_input->psz_name; if( psz_name ) { @@ -1515,17 +1881,32 @@ static void Eject ( intf_thread_t *p_intf ) return; } +static int comp_dir_entries( const void *pp_dir_entry1, + const void *pp_dir_entry2 ) +{ + struct dir_entry_t *p_dir_entry1 = *(struct dir_entry_t**)pp_dir_entry1; + struct dir_entry_t *p_dir_entry2 = *(struct dir_entry_t**)pp_dir_entry2; + if ( p_dir_entry1->b_file == p_dir_entry2->b_file ) { + return strcasecmp( p_dir_entry1->psz_path, p_dir_entry2->psz_path ); + } + else + { + return ( p_dir_entry1->b_file ? 1 : -1 ); + } +} + static void ReadDir( intf_thread_t *p_intf ) { - intf_sys_t *p_sys = p_intf->p_sys; - DIR * p_current_dir; - struct dirent * p_dir_content; + intf_sys_t *p_sys = p_intf->p_sys; + DIR *p_current_dir; int i; if( p_sys->psz_current_dir && *p_sys->psz_current_dir ) { + char *psz_entry; + /* Open the dir */ - p_current_dir = opendir( p_sys->psz_current_dir ); + p_current_dir = utf8_opendir( p_sys->psz_current_dir ); if( p_current_dir == NULL ) { @@ -1538,7 +1919,7 @@ static void ReadDir( intf_thread_t *p_intf ) #endif return; } - + /* Clean the old shit */ for( i = 0; i < p_sys->i_dir_entries; i++ ) { @@ -1551,50 +1932,69 @@ static void ReadDir( intf_thread_t *p_intf ) p_sys->i_dir_entries = 0; /* get the first directory entry */ - p_dir_content = readdir( p_current_dir ); + psz_entry = utf8_readdir( p_current_dir ); /* while we still have entries in the directory */ - while( p_dir_content != NULL ) + while( psz_entry != NULL ) { +#if defined( S_ISDIR ) + struct stat stat_data; +#endif struct dir_entry_t *p_dir_entry; int i_size_entry = strlen( p_sys->psz_current_dir ) + - strlen( p_dir_content->d_name ) + 2; - char *psz_uri = (char *)malloc( sizeof(char)*i_size_entry); + strlen( psz_entry ) + 2; + char *psz_uri; - sprintf( psz_uri, "%s/%s", p_sys->psz_current_dir, p_dir_content->d_name ); + if( p_sys->b_show_hidden_files == VLC_FALSE && + ( strlen( psz_entry ) && psz_entry[0] == '.' ) && + strcmp( psz_entry, ".." ) ) + { + free( psz_entry ); + psz_entry = utf8_readdir( p_current_dir ); + continue; + } - if( ( p_dir_entry = malloc( sizeof( struct dir_entry_t) ) ) == NULL ) + psz_uri = (char *)malloc( sizeof(char)*i_size_entry); + sprintf( psz_uri, "%s/%s", p_sys->psz_current_dir, psz_entry ); + + if( !( p_dir_entry = malloc( sizeof( struct dir_entry_t) ) ) ) { free( psz_uri); return; } #if defined( S_ISDIR ) - struct stat stat_data; - stat( psz_uri, &stat_data ); + utf8_stat( psz_uri, &stat_data ); if( S_ISDIR(stat_data.st_mode) ) -#elif defined( DT_DIR ) - if( p_dir_content->d_type & DT_DIR ) +/*#elif defined( DT_DIR ) + if( p_dir_content->d_type & DT_DIR )*/ #else if( 0 ) #endif { - p_dir_entry->psz_path = strdup( p_dir_content->d_name ); + p_dir_entry->psz_path = strdup( psz_entry ); p_dir_entry->b_file = VLC_FALSE; INSERT_ELEM( p_sys->pp_dir_entries, p_sys->i_dir_entries, p_sys->i_dir_entries, p_dir_entry ); } else { - p_dir_entry->psz_path = strdup( p_dir_content->d_name ); + p_dir_entry->psz_path = strdup( psz_entry ); p_dir_entry->b_file = VLC_TRUE; INSERT_ELEM( p_sys->pp_dir_entries, p_sys->i_dir_entries, p_sys->i_dir_entries, p_dir_entry ); } + free( psz_uri ); + free( psz_entry ); /* Read next entry */ - p_dir_content = readdir( p_current_dir ); + psz_entry = utf8_readdir( p_current_dir ); } + + /* Sort */ + qsort( p_sys->pp_dir_entries, p_sys->i_dir_entries, + sizeof(struct dir_entry_t*), &comp_dir_entries ); + closedir( p_current_dir ); return; } @@ -1632,12 +2032,12 @@ static void PlayPause( intf_thread_t *p_intf ) /**************************************************************************** * ****************************************************************************/ -static void DrawBox( WINDOW *win, int y, int x, int h, int w, char *title ) +static void DrawBox( WINDOW *win, int y, int x, int h, int w, const char *title ) { int i; int i_len; - if( w > 3 && h > 2 ) + if( w > 3 && h > 2 ) { if( title == NULL ) title = ""; i_len = strlen( title ); @@ -1676,6 +2076,6 @@ static void DrawLine( WINDOW *win, int y, int x, int w ) { attrset( A_REVERSE ); mvhline( y, x, ' ', w ); - attroff ( A_REVERSE ); + attroff( A_REVERSE ); } }