X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fncurses.c;h=f20e1185b2592cfa3b8e53f440a589732968bc89;hb=87c76c20237a663506a2deed9f8db9af732fee47;hp=969d6fca75cafd0fee82ba5c0c99fa11852d33f4;hpb=dcddb65e52f7544f600642d0bd03b87656bfecc6;p=vlc diff --git a/modules/gui/ncurses.c b/modules/gui/ncurses.c index 969d6fca75..f20e1185b2 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 the VideoLAN team + * Copyright (C) 2001-2006 the VideoLAN team * $Id$ * * Authors: Sam Hocevar @@ -27,18 +27,23 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* malloc(), free() */ -#include +#include + #include /* ENOMEM */ -#include #include -#include +#ifdef HAVE_NCURSESW +# define _XOPEN_SOURCE_EXTENDED 1 +#endif -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include +#include #ifdef HAVE_SYS_STAT_H # include @@ -57,7 +62,7 @@ #ifdef HAVE_VCDX #define VCD_MRL "vcdx://" #else -#define VCD_MRL "vcdx://" +#define VCD_MRL "vcd://" #endif #define SEARCH_CHAIN_SIZE 20 @@ -75,14 +80,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, char *); +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 * ); @@ -100,7 +110,7 @@ vlc_module_begin(); set_description( _("Ncurses interface") ); set_capability( "interface", 10 ); set_category( CAT_INTERFACE ); - set_subcategory( SUBCAT_INTERFACE_GENERAL ); + set_subcategory( SUBCAT_INTERFACE_MAIN ); set_callbacks( Open, Close ); add_shortcut( "curses" ); add_directory( "browse-dir", NULL, NULL, BROWSE_TEXT, BROWSE_LONGTEXT, VLC_FALSE ); @@ -120,6 +130,11 @@ enum BOX_OPEN, BOX_BROWSE }; +enum +{ + VIEW_CATEGORY, + VIEW_ONELEVEL +}; struct dir_entry_t { vlc_bool_t b_file; @@ -148,7 +163,6 @@ 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; @@ -160,6 +174,7 @@ 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; @@ -169,7 +184,9 @@ struct intf_sys_t 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 */ + vlc_bool_t b_need_update; /* for playlist view */ + + int i_verbose; /* stores verbosity level */ }; static void DrawBox( WINDOW *win, int y, int x, int h, int w, const char *title ); @@ -198,9 +215,9 @@ 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_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(); @@ -220,9 +237,12 @@ static int Open( vlc_object_t *p_this ) /* exported function */ p_intf->pf_run = Run; + /* Remember verbosity level */ + var_Get( p_intf->p_libvlc, "verbose", &val ); + p_sys->i_verbose = val.i_int; /* 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; @@ -249,7 +269,7 @@ static int Open( vlc_object_t *p_this ) } 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; @@ -304,6 +324,11 @@ static void Close( vlc_object_t *p_this ) msg_Unsubscribe( p_intf, p_sys->p_sub ); + /* Restores initial verbose setting */ + vlc_value_t val; + val.i_int = p_sys->i_verbose; + var_Set( p_intf->p_libvlc, "verbose", val ); + /* Destroy structure */ free( p_sys ); } @@ -323,7 +348,7 @@ 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 ); @@ -364,12 +389,12 @@ 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 ) { FindIndex( p_intf ); } - while( ( i_key = getch()) != -1 ) + while( ( i_key = getch() ) != -1 ) { /* * HandleKey returns 1 if the screen needs to be redrawn @@ -399,11 +424,46 @@ static void Run( intf_thread_t *p_intf ) } /* following functions are local */ - -static inline const char *KeyToUTF8( int i_key ) +static char *KeyToUTF8( int i_key, char *psz_part ) { - char local[2] = { (char)i_key, 0 }; - return FromLocaleDup( local ); + char *psz_utf8; + 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; + +#ifdef HAVE_NCURSESW + psz_utf8 = strdup( psz_part ); +#else + psz_utf8 = FromLocaleDup( psz_part ); + + /* Ugly check for incomplete bytes sequences + * (in case of non-UTF8 multibyte local encoding) */ + char *psz; + 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; + } +#endif + + memset( psz_part, 0, 6 ); + return psz_utf8; } static inline int RemoveLastUTF8Entity( char *psz, int len ) @@ -423,6 +483,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 ) { @@ -446,10 +507,16 @@ 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 */ @@ -457,13 +524,13 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) switch( p_sys->i_current_view ) { case VIEW_CATEGORY: - p_sys->i_current_view = VIEW_ALL; + 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 ); - FindIndex( p_intf ); return 1; /* Playlist navigation */ @@ -471,7 +538,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--; @@ -489,40 +556,56 @@ 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_LockDelete( 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_DeleteFromInput( p_playlist, + p_item->p_input->i_id, VLC_TRUE ); + } + else { - playlist_Goto( p_sys->p_playlist, i_item ); + 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: - if( p_sys->i_current_view == VIEW_ALL ) + if( !p_sys->pp_plist || !p_sys->pp_plist[p_sys->i_box_plidx] ) { - playlist_Goto( p_sys->p_playlist, p_sys->i_box_plidx ); + b_ret = VLC_FALSE; + break; + } + if( p_sys->pp_plist[p_sys->i_box_plidx]->p_item->i_children + == -1 ) + { + playlist_item_t *p_item, *p_parent; + p_item = p_parent = + p_sys->pp_plist[p_sys->i_box_plidx]->p_item; + + if( !p_parent ) + p_parent = p_sys->p_playlist->p_root_onelevel; + while( p_parent->p_parent ) + p_parent = p_parent->p_parent; + playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY, + VLC_TRUE, p_parent, p_item ); } else { - if( p_sys->pp_plist[p_sys->i_box_plidx]->p_item->i_children - == -1 ) - { - playlist_Control( p_sys->p_playlist, PLAYLIST_ITEMPLAY, - p_sys->pp_plist[p_sys->i_box_plidx]->p_item ); - } - else - { - playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY, - p_sys->i_current_view, - p_sys->pp_plist[p_sys->i_box_plidx]->p_item, - NULL ); - } + playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY, + VLC_TRUE, + p_sys->pp_plist[p_sys->i_box_plidx]->p_item, + NULL ); } - p_sys->b_box_plidx_follow = VLC_TRUE; + b_box_plidx_follow = VLC_TRUE; break; default: b_ret = VLC_FALSE; @@ -532,25 +615,12 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) if( b_ret ) { int i_max = p_sys->i_plist_entries; - if( p_sys->i_current_view == VIEW_ALL ) - i_max = p_sys->p_playlist->i_size; 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_current_view == VIEW_ALL ) - { - 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; - } - else - { - if( p_sys->pp_plist[p_sys->i_box_plidx]->p_item == - p_sys->p_playlist->status.p_item ) - 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; } } @@ -594,9 +664,18 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) 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_bidx]->psz_path ); - playlist_Add( p_sys->p_playlist, psz_uri, - psz_uri, - PLAYLIST_APPEND, PLAYLIST_END ); + + playlist_item_t *p_parent = p_sys->p_playlist->status.p_node; + if( !p_parent ) + p_parent = p_sys->p_playlist->p_root_onelevel; + + while( p_parent->p_parent ) + p_parent = p_parent->p_parent; + + playlist_Add( p_sys->p_playlist, psz_uri, NULL, + PLAYLIST_APPEND, PLAYLIST_END, + p_parent == p_sys->p_playlist->p_root_onelevel + , VLC_FALSE ); p_sys->i_box_type = BOX_PLAYLIST; free( psz_uri ); } @@ -715,13 +794,17 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) break; default: { - const char *psz_utf8 = KeyToUTF8( i_key ); + char *psz_utf8 = KeyToUTF8( i_key, p_sys->psz_partial_keys ); - if( i_chain_len + strlen( psz_utf8 ) < SEARCH_CHAIN_SIZE ) + if( psz_utf8 != NULL ) { - strcpy( p_sys->psz_search_chain + i_chain_len, psz_utf8 ); + if( i_chain_len + strlen( psz_utf8 ) < SEARCH_CHAIN_SIZE ) + { + strcpy( p_sys->psz_search_chain + i_chain_len, + psz_utf8 ); + } + free( psz_utf8 ); } - LocaleFree( psz_utf8 ); break; } } @@ -747,9 +830,17 @@ 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 ); + playlist_item_t *p_parent = p_sys->p_playlist->status.p_node; + if( !p_parent ) + p_parent = p_sys->p_playlist->p_root_onelevel; + + while( p_parent->p_parent ) + p_parent = p_parent->p_parent; + + playlist_Add( p_playlist, p_sys->psz_open_chain, NULL, + PLAYLIST_APPEND|PLAYLIST_GO, PLAYLIST_END, + p_parent == p_sys->p_playlist->p_root_onelevel + , VLC_FALSE ); p_sys->b_box_plidx_follow = VLC_TRUE; } p_sys->i_box_type = BOX_PLAYLIST; @@ -762,14 +853,17 @@ static int HandleKey( intf_thread_t *p_intf, int i_key ) break; default: { - const char *psz_utf8 = KeyToUTF8( i_key ); + char *psz_utf8 = KeyToUTF8( i_key, p_sys->psz_partial_keys ); - if( i_chain_len + strlen( psz_utf8 ) < OPEN_CHAIN_SIZE ) + if( psz_utf8 != NULL ) { - strcpy( p_sys->psz_open_chain + i_chain_len, psz_utf8 ); - i_chain_len += strlen( psz_utf8 ); + if( i_chain_len + strlen( psz_utf8 ) < OPEN_CHAIN_SIZE ) + { + strcpy( p_sys->psz_open_chain + i_chain_len, + psz_utf8 ); + } + free( psz_utf8 ); } - LocaleFree( psz_utf8 ); break; } } @@ -783,7 +877,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 */ @@ -1012,7 +1106,6 @@ static void SearchPlaylist( intf_thread_t *p_intf, char *psz_searchstring ) 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 ) { @@ -1025,8 +1118,7 @@ static void SearchPlaylist( intf_thread_t *p_intf, char *psz_searchstring ) return; } - i_max = p_sys->i_current_view == VIEW_ALL ? - p_playlist->i_size : p_sys->i_plist_entries; + i_max = p_sys->i_plist_entries; i_item = SubSearchPlaylist( p_intf, psz_searchstring, i_first + 1, i_max ); if( i_item < 0 ) @@ -1043,33 +1135,15 @@ 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; - playlist_t *p_playlist = p_sys->p_playlist; int i, i_item = -1; - if( p_sys->i_current_view == VIEW_ALL ) - { - for( i = i_start + 1; i < i_stop; i++ ) - { - if( strcasestr( p_playlist->pp_items[i]->input.psz_name, - psz_searchstring ) != NULL - || strcasestr( p_playlist->pp_items[i]->input.psz_uri, - psz_searchstring ) != NULL ) - { - i_item = i; - break; - } - } - } - else + for( i = i_start + 1; i < i_stop; i++ ) { - for( i = i_start + 1; i < i_stop; i++ ) + if( strcasestr( p_sys->pp_plist[i]->psz_display, + psz_searchstring ) != NULL ) { - if( strcasestr( p_sys->pp_plist[i]->psz_display, - psz_searchstring ) != NULL ) - { - i_item = i; - break; - } + i_item = i; + break; } } @@ -1082,46 +1156,73 @@ static void mvnprintw( int y, int x, int w, const char *p_fmt, ... ) va_list vl_args; char *p_buf = NULL; int i_len; +#ifdef HAVE_NCURSESW + size_t i_char_len; /* UCS character length */ + size_t i_width; /* Display width */ + wchar_t *psz_wide; /* wchar_t representation of p_buf */ +#endif va_start( vl_args, p_fmt ); - vasprintf( &p_buf, p_fmt, vl_args ); + if( vasprintf( &p_buf, p_fmt, vl_args ) == -1 ) + return; va_end( vl_args ); - if( p_buf == NULL ) - { + if( ( p_buf == NULL ) || ( w <= 0 ) ) return; - } - if( w > 0 ) + + i_len = strlen( p_buf ); +#ifdef HAVE_NCURSESW + psz_wide = (wchar_t *) malloc( sizeof( wchar_t ) * ( i_len + 1 ) ); + + i_char_len = mbstowcs( psz_wide, p_buf, i_len ); + + if( i_char_len == (size_t)-1 ) /* an invalid character was encountered */ + i_width = i_len; + else { - 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; + i_width = wcswidth( psz_wide, i_char_len ); + if( i_width == (size_t)-1 ) /* a non printable character was encountered */ + i_width = i_len; + } + if( i_width > (size_t)w ) +#else + if( i_len > w ) +#endif + { /* FIXME: ncursesw: ellipsize psz_wide while keeping the width in mind */ + int i_cut = i_len - w; + int x1 = i_len/2 - i_cut/2; + int x2 = x1 + i_cut; - if( i_len > x2 ) - { - memmove( &p_buf[x1], &p_buf[x2], i_len - x2 ); - } - p_buf[w] = '\0'; - if( w > 7 ) - { - p_buf[w/2-1] = '.'; - p_buf[w/2 ] = '.'; - p_buf[w/2+1] = '.'; - } - psz_local = ToLocale( p_buf ); - mvprintw( y, x, "%s", psz_local ); - LocaleFree( p_buf ); + if( i_len > x2 ) + { + memmove( &p_buf[x1], &p_buf[x2], i_len - x2 ); } - else + p_buf[w] = '\0'; + if( w > 7 ) { - char *psz_local = ToLocale( p_buf ); - mvprintw( y, x, "%s", psz_local ); - LocaleFree( p_buf ); - mvhline( y, x + i_len, ' ', w - i_len ); + p_buf[w/2-1] = '.'; + p_buf[w/2 ] = '.'; + p_buf[w/2+1] = '.'; } +#ifdef HAVE_NCURSESW + mvprintw( y, x, "%s", p_buf ); +#else + char *psz_local = ToLocale( p_buf ); + mvprintw( y, x, "%s", psz_local ); + LocaleFree( p_buf ); +#endif + } + else + { +#ifdef HAVE_NCURSESW + mvprintw( y, x, "%s", p_buf ); + mvhline( y, x + i_width, ' ', w - i_width ); +#else + char *psz_local = ToLocale( p_buf ); + mvprintw( y, x, "%s", psz_local ); + LocaleFree( p_buf ); + mvhline( y, x + i_len, ' ', w - i_len ); +#endif } } static void MainBoxWrite( intf_thread_t *p_intf, int l, int x, const char *p_fmt, ... ) @@ -1137,7 +1238,8 @@ static void MainBoxWrite( intf_thread_t *p_intf, int l, int x, const char *p_fmt } va_start( vl_args, p_fmt ); - vasprintf( &p_buf, p_fmt, vl_args ); + if( vasprintf( &p_buf, p_fmt, vl_args ) == -1 ) + return; va_end( vl_args ); if( p_buf == NULL ) @@ -1156,7 +1258,7 @@ static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh ) int h; int y_end; - //clear(); + clear(); /* Title */ attrset( A_REVERSE ); @@ -1173,23 +1275,40 @@ 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->input.p_item->psz_uri ); + char *psz_uri = input_item_GetURI( input_GetItem( p_input ) ); + mvnprintw( y++, 0, COLS, " Source : %s", psz_uri ); + free( psz_uri ); /* State */ var_Get( p_input, "state", &val ); if( val.i_int == PLAYING_S ) { - mvnprintw( y++, 0, COLS, " State : Playing" ); + mvnprintw( y, 0, COLS, " State : Playing" ); } - else if( val.i_int == PAUSE_S ) + else if( val.i_int == OPENING_S ) { - mvnprintw( y++, 0, COLS, " State : Paused" ); + mvnprintw( y, 0, COLS, " State : Opening/Connecting" ); } - else + else if( val.i_int == BUFFERING_S ) { - y++; + mvnprintw( y, 0, COLS, " State : Buffering" ); } + else if( val.i_int == PAUSE_S ) + { + mvnprintw( y, 0, COLS, " State : Paused" ); + } + char *psz_playlist_state = malloc( 25 ); + /* strlen( "[Repeat] [Random] [Loop] ) == 24, + '\0' */ + psz_playlist_state[0] = '\0'; + if( var_GetBool( p_sys->p_playlist, "repeat" ) ) + strcat( psz_playlist_state, "[Repeat] " ); + if( var_GetBool( p_sys->p_playlist, "random" ) ) + strcat( psz_playlist_state, "[Random] " ); + if( var_GetBool( p_sys->p_playlist, "loop" ) ) + strcat( psz_playlist_state, "[Loop]" ); + mvnprintw( y++, 32, COLS, psz_playlist_state ); + free( psz_playlist_state ); + if( val.i_int != INIT_S && val.i_int != END_S ) { audio_volume_t i_volume; @@ -1335,10 +1454,10 @@ static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh ) if( p_input ) { int i,j; - vlc_mutex_lock( &p_input->input.p_item->lock ); - for( i = 0; i < p_input->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->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++ ) @@ -1348,7 +1467,7 @@ static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh ) MainBoxWrite( p_intf, l++, 1, " %s: %s", p_info->psz_name, p_info->psz_value ); } } - vlc_mutex_unlock( &p_input->input.p_item->lock ); + vlc_mutex_unlock( &input_GetItem(p_input)->lock ); } else { @@ -1464,16 +1583,14 @@ 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, i_max = p_sys->i_plist_entries; int i_item; char *psz_title; switch( p_sys->i_current_view ) { - case VIEW_ALL: - psz_title = strdup( " Playlist (All, unsorted) " ); - i_max = p_playlist->i_size; + case VIEW_ONELEVEL: + psz_title = strdup( " Playlist (All, one level) " ); break; case VIEW_CATEGORY: psz_title = strdup( " Playlist (By category) " ); @@ -1484,8 +1601,7 @@ static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh ) DrawBox( p_sys->w, y++, 0, h, COLS, psz_title ); - if( p_sys->i_current_view != VIEW_ALL && - ( p_sys->b_need_update || p_sys->pp_plist == NULL ) ) + if( p_sys->b_need_update || p_sys->pp_plist == NULL ) { PlaylistRebuild( p_intf ); } @@ -1495,6 +1611,8 @@ static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh ) } 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 ) { @@ -1520,50 +1638,11 @@ static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh ) i_stop = i_max; } - if( p_sys->i_current_view == VIEW_ALL ) - { - 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 ? '>' : ' '; - - 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 ); - } - if( b_selected ) - { - attroff( A_REVERSE ); - } - } - - } - else - { - - 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->status.p_item == - p_sys->pp_plist[i_item]->p_item ) ? '>' : ' '; + int c = ( PlaylistIsPlaying( p_intf, + p_sys->pp_plist[i_item]->p_item ) ) ? '>' : ' '; if( y >= y_end ) break; if( b_selected ) @@ -1578,7 +1657,6 @@ static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh ) } } - } } else { @@ -1620,10 +1698,28 @@ static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh ) *t_last_refresh = time( 0 ); } +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_view_t *p_view; playlist_t *p_playlist = p_sys->p_playlist; if( p_playlist == NULL ) @@ -1633,13 +1729,11 @@ static void PlaylistRebuild( intf_thread_t *p_intf ) vlc_mutex_lock( &p_playlist->object_lock ); - p_view = playlist_ViewFind( p_playlist, p_intf->p_sys->i_current_view ); - /* First clear the old one */ PlaylistDestroy( p_intf ); /* Build the new one */ - PlaylistAddNode( p_intf, p_view->p_root, 0, "" ); + PlaylistAddNode( p_intf, PlaylistGetRoot( p_intf ), 0, "" ); p_sys->b_need_update = VLC_FALSE; @@ -1647,7 +1741,7 @@ static void PlaylistRebuild( intf_thread_t *p_intf ) } static void PlaylistAddNode( intf_thread_t *p_intf, playlist_item_t *p_node, - int i, char *c ) + int i, const char *c ) { intf_sys_t *p_sys = p_intf->p_sys; playlist_item_t *p_child; @@ -1663,19 +1757,19 @@ static void PlaylistAddNode( intf_thread_t *p_intf, playlist_item_t *p_node, int i_size; p_child = p_node->pp_children[k]; - i_size = strlen( c ) + strlen( p_child->input.psz_name ) + 4; + 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( p_pl_item == NULL || buff == NULL ) return; if( strlen( c ) ) { sprintf( buff, "%s%c-%s", c, k == p_node->i_children - 1 ? - '`' : '|', p_child->input.psz_name ); + '`' : '|', p_child->p_input->psz_name ); } else { - sprintf( buff, " %s", p_child->input.psz_name ); + sprintf( buff, " %s", p_child->p_input->psz_name ); } p_pl_item->psz_display = strdup( buff ); p_pl_item->p_item = p_child; @@ -1703,27 +1797,35 @@ static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable, 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_current_view == VIEW_ALL ) + 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 ) ) { - p_sys->i_box_plidx = p_sys->p_playlist->i_index; + return; } - else if( ( p_sys->i_box_plidx < p_sys->i_plist_entries && - p_sys->pp_plist[p_sys->i_box_plidx]->p_item != - p_sys->p_playlist->status.p_item ) ) + + for( i = 0; i < p_sys->i_plist_entries; i++ ) { - for( i = 0; i < p_sys->i_plist_entries; i++ ) + if( PlaylistIsPlaying( p_intf, p_sys->pp_plist[i]->p_item ) ) { - if( p_sys->pp_plist[i]->p_item == - p_sys->p_playlist->status.p_item ) - { - p_sys->i_box_plidx = i; - break; - } + p_sys->i_box_plidx = i; + break; } } } @@ -1764,14 +1866,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 ) { @@ -1862,7 +1964,7 @@ static int comp_dir_entries( const void *pp_dir_entry1, if ( p_dir_entry1->b_file == p_dir_entry2->b_file ) { return strcasecmp( p_dir_entry1->psz_path, p_dir_entry2->psz_path ); } - else + else { return ( p_dir_entry1->b_file ? 1 : -1 ); } @@ -1870,13 +1972,13 @@ static int comp_dir_entries( const void *pp_dir_entry1, static void ReadDir( intf_thread_t *p_intf ) { - intf_sys_t *p_sys = p_intf->p_sys; - DIR * p_current_dir; + 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 ) { - const char *psz_entry; + char *psz_entry; /* Open the dir */ p_current_dir = utf8_opendir( p_sys->psz_current_dir ); @@ -1884,12 +1986,8 @@ static void ReadDir( intf_thread_t *p_intf ) if( p_current_dir == NULL ) { /* something went bad, get out of here ! */ -#ifdef HAVE_ERRNO_H - msg_Warn( p_intf, "cannot open directory `%s' (%s)", - p_sys->psz_current_dir, strerror(errno)); -#else - msg_Warn( p_intf, "cannot open directory `%s'", p_sys->psz_current_dir ); -#endif + msg_Warn( p_intf, "cannot open directory `%s' (%m)", + p_sys->psz_current_dir ); return; } @@ -1904,11 +2002,8 @@ static void ReadDir( intf_thread_t *p_intf ) p_sys->pp_dir_entries = NULL; p_sys->i_dir_entries = 0; - /* get the first directory entry */ - psz_entry = utf8_readdir( p_current_dir ); - /* while we still have entries in the directory */ - while( psz_entry != NULL ) + while( ( psz_entry = utf8_readdir( p_current_dir ) ) != NULL ) { #if defined( S_ISDIR ) struct stat stat_data; @@ -1918,12 +2013,11 @@ static void ReadDir( intf_thread_t *p_intf ) strlen( psz_entry ) + 2; char *psz_uri; - if( p_sys->b_show_hidden_files == VLC_FALSE && + if( p_sys->b_show_hidden_files == VLC_FALSE && ( strlen( psz_entry ) && psz_entry[0] == '.' ) && strcmp( psz_entry, ".." ) ) { - LocaleFree( psz_entry ); - psz_entry = utf8_readdir( p_current_dir ); + free( psz_entry ); continue; } @@ -1932,13 +2026,14 @@ static void ReadDir( intf_thread_t *p_intf ) if( !( p_dir_entry = malloc( sizeof( struct dir_entry_t) ) ) ) { - free( psz_uri); - return; + free( psz_uri ); + free( psz_entry ); + continue; } #if defined( S_ISDIR ) - utf8_stat( psz_uri, &stat_data ); - if( S_ISDIR(stat_data.st_mode) ) + if( !utf8_stat( psz_uri, &stat_data ) + && S_ISDIR(stat_data.st_mode) ) /*#elif defined( DT_DIR ) if( p_dir_content->d_type & DT_DIR )*/ #else @@ -1959,9 +2054,7 @@ static void ReadDir( intf_thread_t *p_intf ) } free( psz_uri ); - LocaleFree( psz_entry ); - /* Read next entry */ - psz_entry = utf8_readdir( p_current_dir ); + free( psz_entry ); } /* Sort */