Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

ncurses.c

00001 /*****************************************************************************
00002  * ncurses.c : NCurses plugin for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2001-2004 the VideoLAN team
00005  * $Id: ncurses.c 12549 2005-09-14 00:43:57Z yoann $
00006  *
00007  * Authors: Sam Hocevar <[email protected]>
00008  *          Laurent Aimar <[email protected]>
00009  *          Yoann Peronneau <[email protected]>
00010  *          Derk-Jan Hartman <hartman at videolan dot org>
00011  *
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program; if not, write to the Free Software
00024  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028  * Preamble
00029  *****************************************************************************/
00030 #include <stdlib.h>                                      /* malloc(), free() */
00031 #include <string.h>
00032 #include <errno.h>                                                 /* ENOMEM */
00033 #include <stdio.h>
00034 #include <time.h>
00035 
00036 #include <curses.h>
00037 
00038 #include <vlc/vlc.h>
00039 #include <vlc/intf.h>
00040 #include <vlc/vout.h>
00041 #include <vlc/aout.h>
00042 
00043 #ifdef HAVE_SYS_STAT_H
00044 #   include <sys/stat.h>
00045 #endif
00046 #if (!defined( WIN32 ) || defined(__MINGW32__))
00047 /* Mingw has its own version of dirent */
00048 #   include <dirent.h>
00049 #endif
00050 
00051 #ifdef HAVE_CDDAX
00052 #define CDDA_MRL "cddax://"
00053 #else
00054 #define CDDA_MRL "cdda://"
00055 #endif
00056 
00057 #ifdef HAVE_VCDX
00058 #define VCD_MRL "vcdx://"
00059 #else
00060 #define VCD_MRL "vcdx://"
00061 #endif
00062 
00063 #define SEARCH_CHAIN_SIZE 20
00064 #define OPEN_CHAIN_SIZE 50
00065 
00066 /*****************************************************************************
00067  * Local prototypes.
00068  *****************************************************************************/
00069 static int  Open           ( vlc_object_t * );
00070 static void Close          ( vlc_object_t * );
00071 
00072 static void Run            ( intf_thread_t * );
00073 static void PlayPause      ( intf_thread_t * );
00074 static void Eject          ( intf_thread_t * );
00075 
00076 static int  HandleKey      ( intf_thread_t *, int );
00077 static void Redraw         ( intf_thread_t *, time_t * );
00078 static void PlaylistRebuild( intf_thread_t * );
00079 static void PlaylistAddNode( intf_thread_t *, playlist_item_t *, int, char *);
00080 static void PlaylistDestroy( intf_thread_t * );
00081 static int  PlaylistChanged( vlc_object_t *, const char *, vlc_value_t,
00082                              vlc_value_t, void * );
00083 static void FindIndex      ( intf_thread_t * );
00084 static void SearchPlaylist ( intf_thread_t *, char * );
00085 static int  SubSearchPlaylist( intf_thread_t *, char *, int, int );
00086 static void ManageSlider   ( intf_thread_t * );
00087 static void ReadDir        ( intf_thread_t * );
00088 
00089 /*****************************************************************************
00090  * Module descriptor
00091  *****************************************************************************/
00092 
00093 #define BROWSE_TEXT N_("Filebrowser starting point")
00094 #define BROWSE_LONGTEXT N_( \
00095     "This option allows you to specify the directory the ncurses filebrowser " \
00096     "will show you initially.")
00097 
00098 vlc_module_begin();
00099     set_shortname( "Ncurses" );
00100     set_description( _("Ncurses interface") );
00101     set_capability( "interface", 10 );
00102     set_category( CAT_INTERFACE );
00103     set_subcategory( SUBCAT_INTERFACE_GENERAL );
00104     set_callbacks( Open, Close );
00105     add_shortcut( "curses" );
00106     add_directory( "browse-dir", NULL, NULL, BROWSE_TEXT, BROWSE_LONGTEXT, VLC_FALSE );
00107 vlc_module_end();
00108 
00109 /*****************************************************************************
00110  * intf_sys_t: description and status of ncurses interface
00111  *****************************************************************************/
00112 enum
00113 {
00114     BOX_NONE,
00115     BOX_HELP,
00116     BOX_INFO,
00117     BOX_LOG,
00118     BOX_PLAYLIST,
00119     BOX_SEARCH,
00120     BOX_OPEN,
00121     BOX_BROWSE
00122 };
00123 struct dir_entry_t
00124 {
00125     vlc_bool_t  b_file;
00126     char        *psz_path;
00127 };
00128 struct pl_item_t
00129 {
00130     playlist_item_t *p_item;
00131     char            *psz_display;
00132 };
00133 struct intf_sys_t
00134 {
00135     playlist_t     *p_playlist;
00136     input_thread_t *p_input;
00137 
00138     float           f_slider;
00139     float           f_slider_old;
00140 
00141     WINDOW          *w;
00142 
00143     int             i_box_type;
00144     int             i_box_y;
00145     int             i_box_lines;
00146     int             i_box_lines_total;
00147     int             i_box_start;
00148 
00149     int             i_box_plidx;    /* Playlist index */
00150     int             b_box_plidx_follow;
00151     playlist_item_t *p_plnode;      /* Playlist node */
00152     int             i_box_bidx;     /* browser index */
00153 
00154     int             b_box_cleared;
00155 
00156     msg_subscription_t* p_sub;                  /* message bank subscription */
00157 
00158     char            *psz_search_chain;          /* for playlist searching    */
00159     char            *psz_old_search;            /* for searching next        */
00160     int             i_before_search;
00161 
00162     char            *psz_open_chain;
00163 
00164     char            *psz_current_dir;
00165     int             i_dir_entries;
00166     struct dir_entry_t  **pp_dir_entries;
00167     vlc_bool_t      b_show_hidden_files;
00168 
00169     int             i_current_view;             /* playlist view             */
00170     struct pl_item_t    **pp_plist;
00171     int             i_plist_entries;
00172     vlc_bool_t      b_need_update;              /* for playlist view */
00173 };
00174 
00175 static void DrawBox( WINDOW *win, int y, int x, int h, int w, char *title );
00176 static void DrawLine( WINDOW *win, int y, int x, int w );
00177 static void DrawEmptyLine( WINDOW *win, int y, int x, int w );
00178 
00179 /*****************************************************************************
00180  * Open: initialize and create window
00181  *****************************************************************************/
00182 static int Open( vlc_object_t *p_this )
00183 {
00184     intf_thread_t *p_intf = (intf_thread_t *)p_this;
00185     intf_sys_t    *p_sys;
00186     vlc_value_t    val;
00187 
00188     /* Allocate instance and initialize some members */
00189     p_sys = p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
00190     p_sys->p_playlist = NULL;
00191     p_sys->p_input = NULL;
00192     p_sys->f_slider = 0.0;
00193     p_sys->f_slider_old = 0.0;
00194     p_sys->i_box_type = BOX_PLAYLIST;
00195     p_sys->i_box_lines = 0;
00196     p_sys->i_box_start= 0;
00197     p_sys->i_box_lines_total = 0;
00198     p_sys->b_box_plidx_follow = VLC_TRUE;
00199     p_sys->b_box_cleared = VLC_FALSE;
00200     p_sys->i_box_plidx = 0;
00201     p_sys->p_plnode = NULL;
00202     p_sys->i_box_bidx = 0;
00203     p_sys->p_sub = msg_Subscribe( p_intf );
00204 
00205     /* Initialize the curses library */
00206     p_sys->w = initscr();
00207     keypad( p_sys->w, TRUE );
00208     /* Don't do NL -> CR/NL */
00209     nonl();
00210     /* Take input chars one at a time */
00211     cbreak();
00212     /* Don't echo */
00213     noecho();
00214 
00215     curs_set(0);
00216     timeout(0);
00217 
00218     clear();
00219 
00220     /* exported function */
00221     p_intf->pf_run = Run;
00222 
00223     /* Set quiet mode */
00224     val.i_int = -1;
00225     var_Set( p_intf->p_vlc, "verbose", val );
00226 
00227     /* Set defaul playlist view */
00228     p_sys->i_current_view = VIEW_CATEGORY;
00229     p_sys->pp_plist = NULL;
00230     p_sys->i_plist_entries = 0;
00231     p_sys->b_need_update = VLC_FALSE;
00232 
00233     /* Initialize search chain */
00234     p_sys->psz_search_chain = (char *)malloc( SEARCH_CHAIN_SIZE + 1 );
00235     p_sys->psz_old_search = NULL;
00236     p_sys->i_before_search = 0;
00237 
00238     /* Initialize open chain */
00239     p_sys->psz_open_chain = (char *)malloc( OPEN_CHAIN_SIZE + 1 );
00240 
00241     /* Initialize browser options */
00242     var_Create( p_intf, "browse-dir", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
00243     var_Get( p_intf, "browse-dir", &val);
00244 
00245     if( val.psz_string && *val.psz_string )
00246     {
00247         p_sys->psz_current_dir = strdup( val.psz_string);
00248         free( val.psz_string );
00249     }
00250     else
00251     {
00252         p_sys->psz_current_dir = strdup( p_intf->p_vlc->psz_homedir );
00253     }
00254 
00255     p_sys->i_dir_entries = 0;
00256     p_sys->pp_dir_entries = NULL;
00257     p_sys->b_show_hidden_files = VLC_FALSE;
00258     ReadDir( p_intf );
00259 
00260     return VLC_SUCCESS;
00261 }
00262 
00263 /*****************************************************************************
00264  * Close: destroy interface window
00265  *****************************************************************************/
00266 static void Close( vlc_object_t *p_this )
00267 {
00268     intf_thread_t *p_intf = (intf_thread_t *)p_this;
00269     intf_sys_t    *p_sys = p_intf->p_sys;
00270     int i;
00271 
00272     var_DelCallback( p_sys->p_playlist, "intf-change", PlaylistChanged,
00273                      p_intf );
00274     var_DelCallback( p_sys->p_playlist, "item-append", PlaylistChanged,
00275                      p_intf );
00276 
00277     PlaylistDestroy( p_intf );
00278 
00279     for( i = 0; i < p_sys->i_dir_entries; i++ )
00280     {
00281         struct dir_entry_t *p_dir_entry = p_sys->pp_dir_entries[i];
00282         if( p_dir_entry->psz_path ) free( p_dir_entry->psz_path );
00283         REMOVE_ELEM( p_sys->pp_dir_entries, p_sys->i_dir_entries, i );
00284         if( p_dir_entry ) free( p_dir_entry );
00285     }
00286     p_sys->pp_dir_entries = NULL;
00287 
00288     if( p_sys->psz_current_dir ) free( p_sys->psz_current_dir );
00289     if( p_sys->psz_search_chain ) free( p_sys->psz_search_chain );
00290     if( p_sys->psz_old_search ) free( p_sys->psz_old_search );
00291     if( p_sys->psz_open_chain ) free( p_sys->psz_open_chain );
00292 
00293     if( p_sys->p_input )
00294     {
00295         vlc_object_release( p_sys->p_input );
00296     }
00297     if( p_sys->p_playlist )
00298     {
00299         vlc_object_release( p_sys->p_playlist );
00300     }
00301 
00302     /* Close the ncurses interface */
00303     endwin();
00304 
00305     msg_Unsubscribe( p_intf, p_sys->p_sub );
00306 
00307     /* Destroy structure */
00308     free( p_sys );
00309 }
00310 
00311 /*****************************************************************************
00312  * Run: ncurses thread
00313  *****************************************************************************/
00314 static void Run( intf_thread_t *p_intf )
00315 {
00316     intf_sys_t    *p_sys = p_intf->p_sys;
00317 
00318     int i_key;
00319     time_t t_last_refresh;
00320 
00321     /*
00322      * force drawing the interface for the first time
00323      */
00324     t_last_refresh = ( time( 0 ) - 1);
00325 
00326     while( !p_intf->b_die )
00327     {
00328         msleep( INTF_IDLE_SLEEP );
00329 
00330         /* Update the input */
00331         if( p_sys->p_playlist == NULL )
00332         {
00333             p_sys->p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
00334                                                  FIND_ANYWHERE );
00335             if( p_sys->p_playlist )
00336             {
00337                 var_AddCallback( p_sys->p_playlist, "intf-change",
00338                                  PlaylistChanged, p_intf );
00339                 var_AddCallback( p_sys->p_playlist, "item-append",
00340                                  PlaylistChanged, p_intf );
00341             }
00342         }
00343         if( p_sys->p_playlist )
00344         {
00345             vlc_mutex_lock( &p_sys->p_playlist->object_lock );
00346             if( p_sys->p_input == NULL )
00347             {
00348                 p_sys->p_input = p_sys->p_playlist->p_input;
00349                 if( p_sys->p_input )
00350                 {
00351                     if( !p_sys->p_input->b_dead )
00352                     {
00353                         vlc_object_yield( p_sys->p_input );
00354                     }
00355                 }
00356             }
00357             else if( p_sys->p_input->b_dead )
00358             {
00359                 vlc_object_release( p_sys->p_input );
00360                 p_sys->p_input = NULL;
00361                 p_sys->f_slider = p_sys->f_slider_old = 0.0;
00362                 p_sys->b_box_cleared = VLC_FALSE;
00363             }
00364             vlc_mutex_unlock( &p_sys->p_playlist->object_lock );
00365         }
00366 
00367         if( p_sys->b_box_plidx_follow && p_sys->p_playlist->i_index >= 0 )
00368         {
00369             FindIndex( p_intf );
00370         }
00371 
00372         while( ( i_key = getch()) != -1 )
00373         {
00374             /*
00375              * HandleKey returns 1 if the screen needs to be redrawn
00376              */
00377             if( HandleKey( p_intf, i_key ) )
00378             {
00379                 Redraw( p_intf, &t_last_refresh );
00380             }
00381         }
00382         /* Hack */
00383         if( p_sys->f_slider > 0.0001 && !p_sys->b_box_cleared )
00384         {
00385             clear();
00386             Redraw( p_intf, &t_last_refresh );
00387             p_sys->b_box_cleared = VLC_TRUE;
00388         }
00389 
00390         /*
00391          * redraw the screen every second
00392          */
00393         if( (time(0) - t_last_refresh) >= 1 )
00394         {
00395             ManageSlider( p_intf );
00396             Redraw( p_intf, &t_last_refresh );
00397         }
00398     }
00399 }
00400 
00401 /* following functions are local */
00402 
00403 static int HandleKey( intf_thread_t *p_intf, int i_key )
00404 {
00405     intf_sys_t *p_sys = p_intf->p_sys;
00406     vlc_value_t val;
00407 
00408     if( p_sys->i_box_type == BOX_PLAYLIST && p_sys->p_playlist )
00409     {
00410         int b_ret = VLC_TRUE;
00411 
00412         switch( i_key )
00413         {
00414             vlc_value_t val;
00415             /* Playlist Settings */
00416             case 'r':
00417                 var_Get( p_sys->p_playlist, "random", &val );
00418                 val.b_bool = !val.b_bool;
00419                 var_Set( p_sys->p_playlist, "random", val );
00420                 return 1;
00421             case 'l':
00422                 var_Get( p_sys->p_playlist, "loop", &val );
00423                 val.b_bool = !val.b_bool;
00424                 var_Set( p_sys->p_playlist, "loop", val );
00425                 return 1;
00426             case 'R':
00427                 var_Get( p_sys->p_playlist, "repeat", &val );
00428                 val.b_bool = !val.b_bool;
00429                 var_Set( p_sys->p_playlist, "repeat", val );
00430                 return 1;
00431 
00432             /* Playlist sort */
00433             case 'o':
00434                 playlist_Sort( p_sys->p_playlist, SORT_TITLE, ORDER_NORMAL );
00435                 return 1;
00436             case 'O':
00437                 playlist_Sort( p_sys->p_playlist, SORT_TITLE, ORDER_REVERSE );
00438                 return 1;
00439 
00440             /* Playlist view */
00441             case 'v':
00442                 switch( p_sys->i_current_view )
00443                 {
00444                     case VIEW_CATEGORY:
00445                         p_sys->i_current_view = VIEW_ALL;
00446                         break;
00447                     default:
00448                         p_sys->i_current_view = VIEW_CATEGORY;
00449                 }
00450                 PlaylistRebuild( p_intf );
00451                 FindIndex( p_intf );
00452                 return 1;
00453 
00454             /* Playlist navigation */
00455             case KEY_HOME:
00456                 p_sys->i_box_plidx = 0;
00457                 break;
00458             case KEY_END:
00459                 p_sys->i_box_plidx = p_sys->p_playlist->i_size - 1;
00460                 break;
00461             case KEY_UP:
00462                 p_sys->i_box_plidx--;
00463                 break;
00464             case KEY_DOWN:
00465                 p_sys->i_box_plidx++;
00466                 break;
00467             case KEY_PPAGE:
00468                 p_sys->i_box_plidx -= p_sys->i_box_lines;
00469                 break;
00470             case KEY_NPAGE:
00471                 p_sys->i_box_plidx += p_sys->i_box_lines;
00472                 break;
00473             case 'D':
00474             case KEY_BACKSPACE:
00475             case KEY_DC:
00476             {
00477                 int i_item = p_sys->p_playlist->i_index;
00478 
00479                 playlist_LockDelete( p_sys->p_playlist, p_sys->i_box_plidx );
00480                 if( i_item < p_sys->p_playlist->i_size &&
00481                     i_item != p_sys->p_playlist->i_index )
00482                 {
00483                     playlist_Goto( p_sys->p_playlist, i_item );
00484                 }
00485                 break;
00486             }
00487 
00488             case KEY_ENTER:
00489             case 0x0d:
00490                 if( p_sys->i_current_view == VIEW_ALL )
00491                 {
00492                     playlist_Goto( p_sys->p_playlist, p_sys->i_box_plidx );
00493                 }
00494                 else
00495                 {
00496                     if( p_sys->pp_plist[p_sys->i_box_plidx]->p_item->i_children
00497                                 == -1 )
00498                     {
00499                         playlist_Control( p_sys->p_playlist, PLAYLIST_ITEMPLAY,
00500                             p_sys->pp_plist[p_sys->i_box_plidx]->p_item );
00501                     }
00502                     else
00503                     {
00504                         playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY,
00505                             p_sys->i_current_view,
00506                             p_sys->pp_plist[p_sys->i_box_plidx]->p_item,
00507                             NULL );
00508                     }
00509                 }
00510                 p_sys->b_box_plidx_follow = VLC_TRUE;
00511                 break;
00512             default:
00513                 b_ret = VLC_FALSE;
00514                 break;
00515         }
00516 
00517         if( b_ret )
00518         {
00519             int i_max = p_sys->i_plist_entries;
00520             if( p_sys->i_current_view == VIEW_ALL )
00521                 i_max = p_sys->p_playlist->i_size;
00522             if( p_sys->i_box_plidx >= i_max ) p_sys->i_box_plidx = i_max - 1;
00523             if( p_sys->i_box_plidx < 0 ) p_sys->i_box_plidx = 0;
00524             if( p_sys->i_current_view == VIEW_ALL )
00525             {
00526                 if( p_sys->i_box_plidx == p_sys->p_playlist->i_index )
00527                     p_sys->b_box_plidx_follow = VLC_TRUE;
00528                 else
00529                     p_sys->b_box_plidx_follow = VLC_FALSE;
00530             }
00531             else
00532             {
00533                 if( p_sys->pp_plist[p_sys->i_box_plidx]->p_item ==
00534                         p_sys->p_playlist->status.p_item )
00535                     p_sys->b_box_plidx_follow = VLC_TRUE;
00536                 else
00537                     p_sys->b_box_plidx_follow = VLC_FALSE;
00538             }
00539             return 1;
00540         }
00541     }
00542     if( p_sys->i_box_type == BOX_BROWSE )
00543     {
00544         vlc_bool_t b_ret = VLC_TRUE;
00545         /* Browser navigation */
00546         switch( i_key )
00547         {
00548             case KEY_HOME:
00549                 p_sys->i_box_bidx = 0;
00550                 break;
00551             case KEY_END:
00552                 p_sys->i_box_bidx = p_sys->i_dir_entries - 1;
00553                 break;
00554             case KEY_UP:
00555                 p_sys->i_box_bidx--;
00556                 break;
00557             case KEY_DOWN:
00558                 p_sys->i_box_bidx++;
00559                 break;
00560             case KEY_PPAGE:
00561                 p_sys->i_box_bidx -= p_sys->i_box_lines;
00562                 break;
00563             case KEY_NPAGE:
00564                 p_sys->i_box_bidx += p_sys->i_box_lines;
00565                 break;
00566             case '.': /* Toggle show hidden files */
00567                 p_sys->b_show_hidden_files = ( p_sys->b_show_hidden_files ==
00568                     VLC_TRUE ? VLC_FALSE : VLC_TRUE );
00569                 ReadDir( p_intf );
00570                 break;
00571 
00572             case KEY_ENTER:
00573             case 0x0d:
00574             case ' ':
00575                 if( p_sys->pp_dir_entries[p_sys->i_box_bidx]->b_file || i_key == ' ' )
00576                 {
00577                     int i_size_entry = strlen( p_sys->psz_current_dir ) +
00578                                        strlen( p_sys->pp_dir_entries[p_sys->i_box_bidx]->psz_path ) + 2;
00579                     char *psz_uri = (char *)malloc( sizeof(char)*i_size_entry);
00580 
00581                     sprintf( psz_uri, "%s/%s", p_sys->psz_current_dir, p_sys->pp_dir_entries[p_sys->i_box_bidx]->psz_path );
00582                     playlist_Add( p_sys->p_playlist, psz_uri,
00583                                   psz_uri,
00584                                   PLAYLIST_APPEND, PLAYLIST_END );
00585                     p_sys->i_box_type = BOX_PLAYLIST;
00586                     free( psz_uri );
00587                 }
00588                 else
00589                 {
00590                     int i_size_entry = strlen( p_sys->psz_current_dir ) +
00591                                        strlen( p_sys->pp_dir_entries[p_sys->i_box_bidx]->psz_path ) + 2;
00592                     char *psz_uri = (char *)malloc( sizeof(char)*i_size_entry);
00593 
00594                     sprintf( psz_uri, "%s/%s", p_sys->psz_current_dir, p_sys->pp_dir_entries[p_sys->i_box_bidx]->psz_path );
00595 
00596                     p_sys->psz_current_dir = strdup( psz_uri );
00597                     ReadDir( p_intf );
00598                     free( psz_uri );
00599                 }
00600                 break;
00601             default:
00602                 b_ret = VLC_FALSE;
00603                 break;
00604         }
00605         if( b_ret )
00606         {
00607             if( p_sys->i_box_bidx >= p_sys->i_dir_entries ) p_sys->i_box_bidx = p_sys->i_dir_entries - 1;
00608             if( p_sys->i_box_bidx < 0 ) p_sys->i_box_bidx = 0;
00609             return 1;
00610         }
00611     }
00612     else if( p_sys->i_box_type == BOX_HELP || p_sys->i_box_type == BOX_INFO )
00613     {
00614         switch( i_key )
00615         {
00616             case KEY_HOME:
00617                 p_sys->i_box_start = 0;
00618                 return 1;
00619             case KEY_END:
00620                 p_sys->i_box_start = p_sys->i_box_lines_total - 1;
00621                 return 1;
00622             case KEY_UP:
00623                 if( p_sys->i_box_start > 0 ) p_sys->i_box_start--;
00624                 return 1;
00625             case KEY_DOWN:
00626                 if( p_sys->i_box_start < p_sys->i_box_lines_total - 1 )
00627                 {
00628                     p_sys->i_box_start++;
00629                 }
00630                 return 1;
00631             case KEY_PPAGE:
00632                 p_sys->i_box_start -= p_sys->i_box_lines;
00633                 if( p_sys->i_box_start < 0 ) p_sys->i_box_start = 0;
00634                 return 1;
00635             case KEY_NPAGE:
00636                 p_sys->i_box_start += p_sys->i_box_lines;
00637                 if( p_sys->i_box_start >= p_sys->i_box_lines_total )
00638                 {
00639                     p_sys->i_box_start = p_sys->i_box_lines_total - 1;
00640                 }
00641                 return 1;
00642             default:
00643                 break;
00644         }
00645     }
00646     else if( p_sys->i_box_type == BOX_NONE )
00647     {
00648         switch( i_key )
00649         {
00650             case KEY_HOME:
00651                 p_sys->f_slider = 0;
00652                 ManageSlider( p_intf );
00653                 return 1;
00654             case KEY_END:
00655                 p_sys->f_slider = 99.9;
00656                 ManageSlider( p_intf );
00657                 return 1;
00658             case KEY_UP:
00659                 p_sys->f_slider += 5.0;
00660                 if( p_sys->f_slider >= 99.0 ) p_sys->f_slider = 99.0;
00661                 ManageSlider( p_intf );
00662                 return 1;
00663             case KEY_DOWN:
00664                 p_sys->f_slider -= 5.0;
00665                 if( p_sys->f_slider < 0.0 ) p_sys->f_slider = 0.0;
00666                 ManageSlider( p_intf );
00667                 return 1;
00668 
00669             default:
00670                 break;
00671         }
00672     }
00673     else if( p_sys->i_box_type == BOX_SEARCH && p_sys->psz_search_chain )
00674     {
00675         int i_chain_len;
00676         i_chain_len = strlen( p_sys->psz_search_chain );
00677         switch( i_key )
00678         {
00679             case 0x0c:      /* ^l */
00680                 clear();
00681                 return 1;
00682             case KEY_ENTER:
00683             case 0x0d:
00684                 if( i_chain_len > 0 )
00685                 {
00686                     p_sys->psz_old_search = strdup( p_sys->psz_search_chain );
00687                 }
00688                 else if( p_sys->psz_old_search )
00689                 {
00690                     SearchPlaylist( p_intf, p_sys->psz_old_search );
00691                 }
00692                 p_sys->i_box_type = BOX_PLAYLIST;
00693                 return 1;
00694             case 0x1b:      /* Esc. */
00695                 p_sys->i_box_plidx = p_sys->i_before_search;
00696                 p_sys->i_box_type = BOX_PLAYLIST;
00697                 return 1;
00698             case KEY_BACKSPACE:
00699                 if( i_chain_len > 0 )
00700                 {
00701                     p_sys->psz_search_chain[ i_chain_len - 1 ] = '\0';
00702                 }
00703                 break;
00704             default:
00705                 if( i_chain_len < SEARCH_CHAIN_SIZE )
00706                 {
00707                     p_sys->psz_search_chain[ i_chain_len++ ] = i_key;
00708                     p_sys->psz_search_chain[ i_chain_len ] = 0;
00709                 }
00710                 break;
00711         }
00712         if( p_sys->psz_old_search )
00713         {
00714             free( p_sys->psz_old_search );
00715             p_sys->psz_old_search = NULL;
00716         }
00717         SearchPlaylist( p_intf, p_sys->psz_search_chain );
00718         return 1;
00719     }
00720     else if( p_sys->i_box_type == BOX_OPEN && p_sys->psz_open_chain )
00721     {
00722         int i_chain_len = strlen( p_sys->psz_open_chain );
00723         playlist_t *p_playlist = p_sys->p_playlist;
00724 
00725         switch( i_key )
00726         {
00727             case 0x0c:      /* ^l */
00728                 clear();
00729                 return 1;
00730             case KEY_ENTER:
00731             case 0x0d:
00732                 if( p_playlist && i_chain_len > 0 )
00733                 {
00734                     playlist_Add( p_playlist, p_sys->psz_open_chain,
00735                                   p_sys->psz_open_chain,
00736                                   PLAYLIST_GO|PLAYLIST_APPEND, PLAYLIST_END );
00737                     p_sys->b_box_plidx_follow = VLC_TRUE;
00738                 }
00739                 p_sys->i_box_type = BOX_PLAYLIST;
00740                 return 1;
00741             case 0x1b:      /* Esc. */
00742                 p_sys->i_box_type = BOX_PLAYLIST;
00743                 return 1;
00744             case KEY_BACKSPACE:
00745                 if( i_chain_len > 0 )
00746                 {
00747                     p_sys->psz_open_chain[ i_chain_len - 1 ] = '\0';
00748                 }
00749                 break;
00750             default:
00751                 if( i_chain_len < OPEN_CHAIN_SIZE )
00752                 {
00753                     p_sys->psz_open_chain[ i_chain_len++ ] = i_key;
00754                     p_sys->psz_open_chain[ i_chain_len ] = 0;
00755                 }
00756                 break;
00757         }
00758         return 1;
00759     }
00760 
00761 
00762     /* Common keys */
00763     switch( i_key )
00764     {
00765         case 'q':
00766         case 'Q':
00767         case 0x1b:  /* Esc */
00768             p_intf->p_vlc->b_die = VLC_TRUE;
00769             return 0;
00770 
00771         /* Box switching */
00772         case 'i':
00773             if( p_sys->i_box_type == BOX_INFO )
00774                 p_sys->i_box_type = BOX_NONE;
00775             else
00776                 p_sys->i_box_type = BOX_INFO;
00777             p_sys->i_box_lines_total = 0;
00778             return 1;
00779         case 'L':
00780             if( p_sys->i_box_type == BOX_LOG )
00781                 p_sys->i_box_type = BOX_NONE;
00782             else
00783                 p_sys->i_box_type = BOX_LOG;
00784             return 1;
00785         case 'P':
00786             if( p_sys->i_box_type == BOX_PLAYLIST )
00787                 p_sys->i_box_type = BOX_NONE;
00788             else
00789                 p_sys->i_box_type = BOX_PLAYLIST;
00790             return 1;
00791         case 'B':
00792             if( p_sys->i_box_type == BOX_BROWSE )
00793                 p_sys->i_box_type = BOX_NONE;
00794             else
00795                 p_sys->i_box_type = BOX_BROWSE;
00796             return 1;
00797         case 'h':
00798         case 'H':
00799             if( p_sys->i_box_type == BOX_HELP )
00800                 p_sys->i_box_type = BOX_NONE;
00801             else
00802                 p_sys->i_box_type = BOX_HELP;
00803             p_sys->i_box_lines_total = 0;
00804             return 1;
00805         case '/':
00806             if( p_sys->i_box_type != BOX_SEARCH )
00807             {
00808                 if( p_sys->psz_search_chain == NULL )
00809                 {
00810                     return 1;
00811                 }
00812                 p_sys->psz_search_chain[0] = '\0';
00813                 p_sys->b_box_plidx_follow = VLC_FALSE;
00814                 p_sys->i_before_search = p_sys->i_box_plidx;
00815                 p_sys->i_box_type = BOX_SEARCH;
00816             }
00817             return 1;
00818         case 'A': /* Open */
00819             if( p_sys->i_box_type != BOX_OPEN )
00820             {
00821                 if( p_sys->psz_open_chain == NULL )
00822                 {
00823                     return 1;
00824                 }
00825                 p_sys->psz_open_chain[0] = '\0';
00826                 p_sys->i_box_type = BOX_OPEN;
00827             }
00828             return 1;
00829 
00830         /* Navigation */
00831         case KEY_RIGHT:
00832             p_sys->f_slider += 1.0;
00833             if( p_sys->f_slider > 99.9 ) p_sys->f_slider = 99.9;
00834             ManageSlider( p_intf );
00835             return 1;
00836 
00837         case KEY_LEFT:
00838             p_sys->f_slider -= 1.0;
00839             if( p_sys->f_slider < 0.0 ) p_sys->f_slider = 0.0;
00840             ManageSlider( p_intf );
00841             return 1;
00842 
00843         /* Common control */
00844         case 'f':
00845         {
00846             if( p_intf->p_sys->p_input )
00847             {
00848                 vout_thread_t *p_vout;
00849                 p_vout = vlc_object_find( p_intf->p_sys->p_input,
00850                                           VLC_OBJECT_VOUT, FIND_CHILD );
00851                 if( p_vout )
00852                 {
00853                     var_Get( p_vout, "fullscreen", &val );
00854                     val.b_bool = !val.b_bool;
00855                     var_Set( p_vout, "fullscreen", val );
00856                     vlc_object_release( p_vout );
00857                 }
00858                 else
00859                 {
00860                     playlist_t *p_playlist;
00861                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
00862                                                   FIND_ANYWHERE );
00863                     if( p_playlist )
00864                     {
00865                         var_Get( p_playlist, "fullscreen", &val );
00866                         val.b_bool = !val.b_bool;
00867                         var_Set( p_playlist, "fullscreen", val );
00868                         vlc_object_release( p_playlist );
00869                     }
00870                 }
00871             }
00872             return 0;
00873         }
00874 
00875         case ' ':
00876             PlayPause( p_intf );
00877             return 1;
00878 
00879         case 's':
00880             if( p_intf->p_sys->p_playlist )
00881             {
00882                 playlist_Stop( p_intf->p_sys->p_playlist );
00883             }
00884             return 1;
00885 
00886         case 'e':
00887             Eject( p_intf );
00888             return 1;
00889 
00890         case '[':
00891             if( p_sys->p_input )
00892             {
00893                 val.b_bool = VLC_TRUE;
00894                 var_Set( p_sys->p_input, "prev-title", val );
00895             }
00896             return 1;
00897 
00898         case ']':
00899             if( p_sys->p_input )
00900             {
00901                 val.b_bool = VLC_TRUE;
00902                 var_Set( p_sys->p_input, "next-title", val );
00903             }
00904             return 1;
00905 
00906         case '<':
00907             if( p_sys->p_input )
00908             {
00909                 val.b_bool = VLC_TRUE;
00910                 var_Set( p_sys->p_input, "prev-chapter", val );
00911             }
00912             return 1;
00913 
00914         case '>':
00915             if( p_sys->p_input )
00916             {
00917                 val.b_bool = VLC_TRUE;
00918                 var_Set( p_sys->p_input, "next-chapter", val );
00919             }
00920             return 1;
00921 
00922         case 'p':
00923             if( p_intf->p_sys->p_playlist )
00924             {
00925                 playlist_Prev( p_intf->p_sys->p_playlist );
00926             }
00927             clear();
00928             return 1;
00929 
00930         case 'n':
00931             if( p_intf->p_sys->p_playlist )
00932             {
00933                 playlist_Next( p_intf->p_sys->p_playlist );
00934             }
00935             clear();
00936             return 1;
00937 
00938         case 'a':
00939             aout_VolumeUp( p_intf, 1, NULL );
00940             clear();
00941             return 1;
00942 
00943         case 'z':
00944             aout_VolumeDown( p_intf, 1, NULL );
00945             clear();
00946             return 1;
00947 
00948         /*
00949          * ^l should clear and redraw the screen
00950          */
00951         case 0x0c:
00952             clear();
00953             return 1;
00954 
00955         default:
00956             return 0;
00957     }
00958 }
00959 
00960 static void ManageSlider( intf_thread_t *p_intf )
00961 {
00962     intf_sys_t     *p_sys = p_intf->p_sys;
00963     input_thread_t *p_input = p_sys->p_input;
00964     vlc_value_t     val;
00965 
00966     if( p_input == NULL )
00967     {
00968         return;
00969     }
00970     var_Get( p_input, "state", &val );
00971     if( val.i_int != PLAYING_S )
00972     {
00973         return;
00974     }
00975 
00976     var_Get( p_input, "position", &val );
00977     if( p_sys->f_slider == p_sys->f_slider_old )
00978     {
00979         p_sys->f_slider =
00980         p_sys->f_slider_old = 100 * val.f_float;
00981     }
00982     else
00983     {
00984         p_sys->f_slider_old = p_sys->f_slider;
00985 
00986         val.f_float = p_sys->f_slider / 100.0;
00987         var_Set( p_input, "position", val );
00988     }
00989 }
00990 
00991 static void SearchPlaylist( intf_thread_t *p_intf, char *psz_searchstring )
00992 {
00993     int i_max;
00994     int i_first = 0 ;
00995     int i_item = -1;
00996     intf_sys_t *p_sys = p_intf->p_sys;
00997     playlist_t *p_playlist = p_sys->p_playlist;
00998 
00999     if( p_sys->i_before_search >= 0 )
01000     {
01001         i_first = p_sys->i_before_search;
01002     }
01003 
01004     if( ( ! psz_searchstring ) ||  strlen( psz_searchstring ) <= 0 )
01005     {
01006         p_sys->i_box_plidx = p_sys->i_before_search;
01007         return;
01008     }
01009 
01010     i_max = p_sys->i_current_view == VIEW_ALL ?
01011                 p_playlist->i_size : p_sys->i_plist_entries;
01012 
01013     i_item = SubSearchPlaylist( p_intf, psz_searchstring, i_first + 1, i_max );
01014     if( i_item < 0 )
01015     {
01016         i_item = SubSearchPlaylist( p_intf, psz_searchstring, 0, i_first );
01017     }
01018 
01019     if( i_item < 0 || i_item >= i_max ) return;
01020 
01021     p_sys->i_box_plidx = i_item;
01022 }
01023 
01024 static int SubSearchPlaylist( intf_thread_t *p_intf, char *psz_searchstring,
01025                               int i_start, int i_stop )
01026 {
01027     intf_sys_t *p_sys = p_intf->p_sys;
01028     playlist_t *p_playlist = p_sys->p_playlist;
01029     int i, i_item = -1;
01030 
01031     if( p_sys->i_current_view == VIEW_ALL )
01032     {
01033         for( i = i_start + 1; i < i_stop; i++ )
01034         {
01035             if( strcasestr( p_playlist->pp_items[i]->input.psz_name,
01036                             psz_searchstring ) != NULL
01037                 || strcasestr( p_playlist->pp_items[i]->input.psz_uri,
01038                                psz_searchstring ) != NULL )
01039             {
01040                 i_item = i;
01041                 break;
01042             }
01043         }
01044     }
01045     else
01046     {
01047         for( i = i_start + 1; i < i_stop; i++ )
01048         {
01049             if( strcasestr( p_sys->pp_plist[i]->psz_display,
01050                             psz_searchstring ) != NULL )
01051             {
01052                 i_item = i;
01053                 break;
01054             }
01055         }
01056     }
01057 
01058     return i_item;
01059 }
01060 
01061 
01062 static void mvnprintw( int y, int x, int w, const char *p_fmt, ... )
01063 {
01064     va_list  vl_args;
01065     char    *p_buf = NULL;
01066     int      i_len;
01067 
01068     va_start( vl_args, p_fmt );
01069     vasprintf( &p_buf, p_fmt, vl_args );
01070     va_end( vl_args );
01071 
01072     if( p_buf == NULL )
01073     {
01074         return;
01075     }
01076     if(  w > 0 )
01077     {
01078         if( ( i_len = strlen( p_buf ) ) > w )
01079         {
01080             int i_cut = i_len - w;
01081             int x1 = i_len/2 - i_cut/2;
01082             int x2 = x1 + i_cut;
01083 
01084             if( i_len > x2 )
01085             {
01086                 memmove( &p_buf[x1], &p_buf[x2], i_len - x2 );
01087             }
01088             p_buf[w] = '\0';
01089             if( w > 7 )
01090             {
01091                 p_buf[w/2-1] = '.';
01092                 p_buf[w/2  ] = '.';
01093                 p_buf[w/2+1] = '.';
01094             }
01095             mvprintw( y, x, "%s", p_buf );
01096         }
01097         else
01098         {
01099             mvprintw( y, x, "%s", p_buf );
01100             mvhline( y, x + i_len, ' ', w - i_len );
01101         }
01102     }
01103 }
01104 static void MainBoxWrite( intf_thread_t *p_intf, int l, int x, const char *p_fmt, ... )
01105 {
01106     intf_sys_t     *p_sys = p_intf->p_sys;
01107 
01108     va_list  vl_args;
01109     char    *p_buf = NULL;
01110 
01111     if( l < p_sys->i_box_start || l - p_sys->i_box_start >= p_sys->i_box_lines )
01112     {
01113         return;
01114     }
01115 
01116     va_start( vl_args, p_fmt );
01117     vasprintf( &p_buf, p_fmt, vl_args );
01118     va_end( vl_args );
01119 
01120     if( p_buf == NULL )
01121     {
01122         return;
01123     }
01124 
01125     mvnprintw( p_sys->i_box_y + l - p_sys->i_box_start, x, COLS - x - 1, "%s", p_buf );
01126 }
01127 
01128 static void Redraw( intf_thread_t *p_intf, time_t *t_last_refresh )
01129 {
01130     intf_sys_t     *p_sys = p_intf->p_sys;
01131     input_thread_t *p_input = p_sys->p_input;
01132     int y = 0;
01133     int h;
01134     int y_end;
01135 
01136     //clear();
01137 
01138     /* Title */
01139     attrset( A_REVERSE );
01140     mvnprintw( y, 0, COLS, "VLC media player" " (ncurses interface) [ h for help ]" );
01141     attroff( A_REVERSE );
01142     y += 2;
01143 
01144     /* Infos */
01145     if( p_input && !p_input->b_dead )
01146     {
01147         char buf1[MSTRTIME_MAX_SIZE];
01148         char buf2[MSTRTIME_MAX_SIZE];
01149         vlc_value_t val;
01150         vlc_value_t val_list;
01151 
01152         /* Source */
01153         mvnprintw( y++, 0, COLS, " Source   : %s",
01154                    p_input->input.p_item->psz_uri );
01155 
01156         /* State */
01157         var_Get( p_input, "state", &val );
01158         if( val.i_int == PLAYING_S )
01159         {
01160             mvnprintw( y++, 0, COLS, " State    : Playing" );
01161         }
01162         else if( val.i_int == PAUSE_S )
01163         {
01164             mvnprintw( y++, 0, COLS, " State    : Paused" );
01165         }
01166         else
01167         {
01168             y++;
01169         }
01170         if( val.i_int != INIT_S && val.i_int != END_S )
01171         {
01172             audio_volume_t i_volume;
01173 
01174             /* Position */
01175             var_Get( p_input, "time", &val );
01176             msecstotimestr( buf1, val.i_time / 1000 );
01177 
01178             var_Get( p_input, "length", &val );
01179             msecstotimestr( buf2, val.i_time / 1000 );
01180 
01181             mvnprintw( y++, 0, COLS, " Position : %s/%s (%.2f%%)", buf1, buf2, p_sys->f_slider );
01182 
01183             /* Volume */
01184             aout_VolumeGet( p_intf, &i_volume );
01185             mvnprintw( y++, 0, COLS, " Volume   : %i%%", i_volume*200/AOUT_VOLUME_MAX );
01186 
01187             /* Title */
01188             if( !var_Get( p_input, "title", &val ) )
01189             {
01190                 var_Change( p_input, "title", VLC_VAR_GETCHOICES, &val_list, NULL );
01191                 if( val_list.p_list->i_count > 0 )
01192                 {
01193                     mvnprintw( y++, 0, COLS, " Title    : %d/%d", val.i_int, val_list.p_list->i_count );
01194                 }
01195                 var_Change( p_input, "title", VLC_VAR_FREELIST, &val_list, NULL );
01196             }
01197 
01198             /* Chapter */
01199             if( !var_Get( p_input, "chapter", &val ) )
01200             {
01201                 var_Change( p_input, "chapter", VLC_VAR_GETCHOICES, &val_list, NULL );
01202                 if( val_list.p_list->i_count > 0 )
01203                 {
01204                     mvnprintw( y++, 0, COLS, " Chapter  : %d/%d", val.i_int, val_list.p_list->i_count );
01205                 }
01206                 var_Change( p_input, "chapter", VLC_VAR_FREELIST, &val_list, NULL );
01207             }
01208         }
01209         else
01210         {
01211             y += 2;
01212         }
01213     }
01214     else
01215     {
01216         mvnprintw( y++, 0, COLS, "Source: <no current item>" );
01217         DrawEmptyLine( p_sys->w, y++, 0, COLS );
01218         DrawEmptyLine( p_sys->w, y++, 0, COLS );
01219         DrawEmptyLine( p_sys->w, y++, 0, COLS );
01220     }
01221 
01222     DrawBox( p_sys->w, y, 0, 3, COLS, "" );
01223     DrawEmptyLine( p_sys->w, y+1, 1, COLS-2);
01224     DrawLine( p_sys->w, y+1, 1, (int)(p_intf->p_sys->f_slider/100.0 * (COLS -2)) );
01225     y += 3;
01226 
01227     p_sys->i_box_y = y + 1;
01228     p_sys->i_box_lines = LINES - y - 2;
01229 
01230     h = LINES - y;
01231     y_end = y + h - 1;
01232 
01233     if( p_sys->i_box_type == BOX_HELP )
01234     {
01235         /* Help box */
01236         int l = 0;
01237         DrawBox( p_sys->w, y++, 0, h, COLS, " Help " );
01238 
01239         MainBoxWrite( p_intf, l++, 1, "[Display]" );
01240         MainBoxWrite( p_intf, l++, 1, "     h,H         Show/Hide help box" );
01241         MainBoxWrite( p_intf, l++, 1, "     i           Show/Hide info box" );
01242         MainBoxWrite( p_intf, l++, 1, "     L           Show/Hide messages box" );
01243         MainBoxWrite( p_intf, l++, 1, "     P           Show/Hide playlist box" );
01244         MainBoxWrite( p_intf, l++, 1, "     B           Show/Hide filebrowser" );
01245         MainBoxWrite( p_intf, l++, 1, "" );
01246 
01247         MainBoxWrite( p_intf, l++, 1, "[Global]" );
01248         MainBoxWrite( p_intf, l++, 1, "     q, Q        Quit" );
01249         MainBoxWrite( p_intf, l++, 1, "     s           Stop" );
01250         MainBoxWrite( p_intf, l++, 1, "     <space>     Pause/Play" );
01251         MainBoxWrite( p_intf, l++, 1, "     f           Toggle Fullscreen" );
01252         MainBoxWrite( p_intf, l++, 1, "     n, p        Next/Previous playlist item" );
01253         MainBoxWrite( p_intf, l++, 1, "     [, ]        Next/Previous title" );
01254         MainBoxWrite( p_intf, l++, 1, "     <, >        Next/Previous chapter" );
01255         MainBoxWrite( p_intf, l++, 1, "     <right>     Seek +1%%" );
01256         MainBoxWrite( p_intf, l++, 1, "     <left>      Seek -1%%" );
01257         MainBoxWrite( p_intf, l++, 1, "     a           Volume Up" );
01258         MainBoxWrite( p_intf, l++, 1, "     z           Volume Down" );
01259         MainBoxWrite( p_intf, l++, 1, "" );
01260 
01261         MainBoxWrite( p_intf, l++, 1, "[Playlist]" );
01262         MainBoxWrite( p_intf, l++, 1, "     r           Random" );
01263         MainBoxWrite( p_intf, l++, 1, "     l           Loop Playlist" );
01264         MainBoxWrite( p_intf, l++, 1, "     R           Repeat item" );
01265         MainBoxWrite( p_intf, l++, 1, "     o           Order Playlist by title" );
01266         MainBoxWrite( p_intf, l++, 1, "     O           Reverse order Playlist by title" );
01267         MainBoxWrite( p_intf, l++, 1, "     /           Look for an item" );
01268         MainBoxWrite( p_intf, l++, 1, "     A           Add an entry" );
01269         MainBoxWrite( p_intf, l++, 1, "     D, <del>    Delete an entry" );
01270         MainBoxWrite( p_intf, l++, 1, "     <backspace> Delete an entry" );
01271         MainBoxWrite( p_intf, l++, 1, "" );
01272 
01273         MainBoxWrite( p_intf, l++, 1, "[Filebrowser]" );
01274         MainBoxWrite( p_intf, l++, 1, "     <enter>     Add the selected file to the playlist" );
01275         MainBoxWrite( p_intf, l++, 1, "     <space>     Add the selected directory to the playlist" );
01276         MainBoxWrite( p_intf, l++, 1, "     .           Show/Hide hidden files" );
01277         MainBoxWrite( p_intf, l++, 1, "" );
01278 
01279         MainBoxWrite( p_intf, l++, 1, "[Boxes]" );
01280         MainBoxWrite( p_intf, l++, 1, "     <up>,<down>     Navigate through the box line by line" );
01281         MainBoxWrite( p_intf, l++, 1, "     <pgup>,<pgdown> Navigate through the box page by page" );
01282         MainBoxWrite( p_intf, l++, 1, "" );
01283 
01284         MainBoxWrite( p_intf, l++, 1, "[Player]" );
01285         MainBoxWrite( p_intf, l++, 1, "     <up>,<down>     Seek +/-5%%" );
01286         MainBoxWrite( p_intf, l++, 1, "" );
01287 
01288         MainBoxWrite( p_intf, l++, 1, "[Miscellaneous]" );
01289         MainBoxWrite( p_intf, l++, 1, "     Ctrl-l          Refresh the screen" );
01290 
01291         p_sys->i_box_lines_total = l;
01292         if( p_sys->i_box_start >= p_sys->i_box_lines_total )
01293         {
01294             p_sys->i_box_start = p_sys->i_box_lines_total - 1;
01295         }
01296 
01297         if( l - p_sys->i_box_start < p_sys->i_box_lines )
01298         {
01299             y += l - p_sys->i_box_start;
01300         }
01301         else
01302         {
01303             y += p_sys->i_box_lines;
01304         }
01305     }
01306     else if( p_sys->i_box_type == BOX_INFO )
01307     {
01308         /* Info box */
01309         int l = 0;
01310         DrawBox( p_sys->w, y++, 0, h, COLS, " Information " );
01311 
01312         if( p_input )
01313         {
01314             int i,j;
01315             vlc_mutex_lock( &p_input->input.p_item->lock );
01316             for( i = 0; i < p_input->input.p_item->i_categories; i++ )
01317             {
01318                 info_category_t *p_category = p_input->input.p_item->pp_categories[i];
01319                 if( y >= y_end ) break;
01320                 MainBoxWrite( p_intf, l++, 1, "  [%s]", p_category->psz_name );
01321                 for( j = 0; j < p_category->i_infos; j++ )
01322                 {
01323                     info_t *p_info = p_category->pp_infos[j];
01324                     if( y >= y_end ) break;
01325                     MainBoxWrite( p_intf, l++, 1, "      %s: %s", p_info->psz_name, p_info->psz_value );
01326                 }
01327             }
01328             vlc_mutex_unlock( &p_input->input.p_item->lock );
01329         }
01330         else
01331         {
01332             MainBoxWrite( p_intf, l++, 1, "No item currently playing" );
01333         }
01334         p_sys->i_box_lines_total = l;
01335         if( p_sys->i_box_start >= p_sys->i_box_lines_total )
01336         {
01337             p_sys->i_box_start = p_sys->i_box_lines_total - 1;
01338         }
01339 
01340         if( l - p_sys->i_box_start < p_sys->i_box_lines )
01341         {
01342             y += l - p_sys->i_box_start;
01343         }
01344         else
01345         {
01346             y += p_sys->i_box_lines;
01347         }
01348     }
01349     else if( p_sys->i_box_type == BOX_LOG )
01350     {
01351         int i_line = 0;
01352         int i_stop;
01353         int i_start;
01354 
01355         DrawBox( p_sys->w, y++, 0, h, COLS, " Logs " );
01356 
01357         i_start = p_intf->p_sys->p_sub->i_start;
01358 
01359         vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
01360         i_stop = *p_intf->p_sys->p_sub->pi_stop;
01361         vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
01362 
01363         for( ;; )
01364         {
01365             static const char *ppsz_type[4] = { "", "error", "warning", "debug" };
01366             if( i_line >= h - 2 )
01367             {
01368                 break;
01369             }
01370             i_stop--;
01371             i_line++;
01372             if( i_stop < 0 ) i_stop += VLC_MSG_QSIZE;
01373             if( i_stop == i_start )
01374             {
01375                 break;
01376             }
01377             mvnprintw( y + h-2-i_line, 1, COLS - 2, "   [%s] %s",
01378                       ppsz_type[p_sys->p_sub->p_msg[i_stop].i_type],
01379                       p_sys->p_sub->p_msg[i_stop].psz_msg );
01380         }
01381 
01382         vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
01383         p_intf->p_sys->p_sub->i_start = i_stop;
01384         vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
01385         y = y_end;
01386     }
01387     else if( p_sys->i_box_type == BOX_BROWSE )
01388     {
01389         /* Filebrowser box */
01390         int        i_start, i_stop;
01391         int        i_item;
01392         DrawBox( p_sys->w, y++, 0, h, COLS, " Browse " );
01393 
01394         if( p_sys->i_box_bidx >= p_sys->i_dir_entries ) p_sys->i_box_plidx = p_sys->i_dir_entries - 1;
01395         if( p_sys->i_box_bidx < 0 ) p_sys->i_box_bidx = 0;
01396 
01397         if( p_sys->i_box_bidx < (h - 2)/2 )
01398         {
01399             i_start = 0;
01400             i_stop = h - 2;
01401         }
01402         else if( p_sys->i_dir_entries - p_sys->i_box_bidx > (h - 2)/2 )
01403         {
01404             i_start = p_sys->i_box_bidx - (h - 2)/2;
01405             i_stop = i_start + h - 2;
01406         }
01407         else
01408         {
01409             i_stop = p_sys->i_dir_entries;
01410             i_start = p_sys->i_dir_entries - (h - 2);
01411         }
01412         if( i_start < 0 )
01413         {
01414             i_start = 0;
01415         }
01416         if( i_stop > p_sys->i_dir_entries )
01417         {
01418             i_stop = p_sys->i_dir_entries;
01419         }
01420 
01421         for( i_item = i_start; i_item < i_stop; i_item++ )
01422         {
01423             vlc_bool_t b_selected = ( p_sys->i_box_bidx == i_item );
01424 
01425             if( y >= y_end ) break;
01426             if( b_selected )
01427             {
01428                 attrset( A_REVERSE );
01429             }
01430             mvnprintw( y++, 1, COLS - 2, " %c %s", p_sys->pp_dir_entries[i_item]->b_file == VLC_TRUE ? ' ' : '+',
01431                             p_sys->pp_dir_entries[i_item]->psz_path );
01432             if( b_selected )
01433             {
01434                 attroff( A_REVERSE );
01435             }
01436         }
01437 
01438     }
01439     else if( ( p_sys->i_box_type == BOX_PLAYLIST ||
01440                p_sys->i_box_type == BOX_SEARCH ||
01441                p_sys->i_box_type == BOX_OPEN  ) && p_sys->p_playlist )
01442     {
01443         /* Playlist box */
01444         playlist_t *p_playlist = p_sys->p_playlist;
01445         int        i_start, i_stop, i_max = p_sys->i_plist_entries;
01446         int        i_item;
01447         char       *psz_title;
01448 
01449         switch( p_sys->i_current_view )
01450         {
01451             case VIEW_ALL:
01452                 psz_title = strdup( " Playlist (All, unsorted) " );
01453                 i_max = p_playlist->i_size;
01454                 break;
01455             case VIEW_CATEGORY:
01456                 psz_title = strdup( " Playlist (By category) " );
01457                 break;
01458             default:
01459                 psz_title = strdup( " Playlist (Manually added) " );
01460         }
01461 
01462         DrawBox( p_sys->w, y++, 0, h, COLS, psz_title );
01463 
01464         if( p_sys->i_current_view != VIEW_ALL &&
01465                 ( p_sys->b_need_update || p_sys->pp_plist == NULL ) )
01466         {
01467             PlaylistRebuild( p_intf );
01468         }
01469         if( p_sys->b_box_plidx_follow )
01470         {
01471             FindIndex( p_intf );
01472         }
01473 
01474         if( p_sys->i_box_plidx < 0 ) p_sys->i_box_plidx = 0;
01475 
01476         if( p_sys->i_box_plidx < (h - 2)/2 )
01477         {
01478             i_start = 0;
01479             i_stop = h - 2;
01480         }
01481         else if( i_max - p_sys->i_box_plidx > (h - 2)/2 )
01482         {
01483             i_start = p_sys->i_box_plidx - (h - 2)/2;
01484             i_stop = i_start + h - 2;
01485         }
01486         else
01487         {
01488             i_stop = i_max;
01489             i_start = i_max - (h - 2);
01490         }
01491         if( i_start < 0 )
01492         {
01493             i_start = 0;
01494         }
01495         if( i_stop > i_max )
01496         {
01497             i_stop = i_max;
01498         }
01499 
01500        if( p_sys->i_current_view == VIEW_ALL )
01501        {
01502 
01503         for( i_item = i_start; i_item < i_stop; i_item++ )
01504         {
01505             vlc_bool_t b_selected = ( p_sys->i_box_plidx == i_item );
01506             int c = p_playlist->i_index == i_item ? '>' : ' ';
01507 
01508             if( y >= y_end ) break;
01509             if( b_selected )
01510             {
01511                 attrset( A_REVERSE );
01512             }
01513             if( !strcmp( p_playlist->pp_items[i_item]->input.psz_name,
01514                          p_playlist->pp_items[i_item]->input.psz_uri ) )
01515             {
01516                 mvnprintw( y++, 1, COLS - 2, "%c %d - '%s'",
01517                            c,
01518                            i_item,
01519                            p_playlist->pp_items[i_item]->input.psz_uri );
01520             }
01521             else
01522             {
01523                 mvnprintw( y++, 1, COLS - 2, "%c %d - '%s' (%s)",
01524                           c,
01525                           i_item,
01526                           p_playlist->pp_items[i_item]->input.psz_uri,
01527                           p_playlist->pp_items[i_item]->input.psz_name );
01528             }
01529             if( b_selected )
01530             {
01531                 attroff( A_REVERSE );
01532             }
01533         }
01534 
01535        }
01536        else
01537        {
01538 
01539         for( i_item = i_start; i_item < i_stop; i_item++ )
01540         {
01541             vlc_bool_t b_selected = ( p_sys->i_box_plidx == i_item );
01542             int c = ( p_playlist->status.p_item ==
01543                           p_sys->pp_plist[i_item]->p_item ) ? '>' : ' ';
01544 
01545             if( y >= y_end ) break;
01546             if( b_selected )
01547             {
01548                 attrset( A_REVERSE );
01549             }
01550             mvnprintw( y++, 1, COLS - 2, "%c%s", c,
01551                        p_sys->pp_plist[i_item]->psz_display );
01552             if( b_selected )
01553             {
01554                 attroff( A_REVERSE );
01555             }
01556         }
01557 
01558        }
01559     }
01560     else
01561     {
01562         y++;
01563     }
01564     if( p_sys->i_box_type == BOX_SEARCH )
01565     {
01566         DrawEmptyLine( p_sys->w, 7, 1, COLS-2 );
01567         if( p_sys->psz_search_chain )
01568         {
01569             if( strlen( p_sys->psz_search_chain ) == 0 &&
01570                 p_sys->psz_old_search != NULL )
01571             {
01572                 /* Searching next entry */
01573                 mvnprintw( 7, 1, COLS-2, "Find: %s", p_sys->psz_old_search );
01574             }
01575             else
01576             {
01577                 mvnprintw( 7, 1, COLS-2, "Find: %s", p_sys->psz_search_chain );
01578             }
01579         }
01580     }
01581     if( p_sys->i_box_type == BOX_OPEN )
01582     {
01583         if( p_sys->psz_open_chain )
01584         {
01585             DrawEmptyLine( p_sys->w, 7, 1, COLS-2 );
01586             mvnprintw( 7, 1, COLS-2, "Open: %s", p_sys->psz_open_chain );
01587         }
01588     }
01589 
01590     while( y < y_end )
01591     {
01592         DrawEmptyLine( p_sys->w, y++, 1, COLS - 2 );
01593     }
01594 
01595     refresh();
01596 
01597     *t_last_refresh = time( 0 );
01598 }
01599 
01600 static void PlaylistRebuild( intf_thread_t *p_intf )
01601 {
01602     intf_sys_t *p_sys = p_intf->p_sys;
01603     playlist_view_t *p_view;
01604     playlist_t *p_playlist = p_sys->p_playlist;
01605 
01606     if( p_playlist == NULL )
01607     {
01608         return;
01609     }
01610 
01611     vlc_mutex_lock( &p_playlist->object_lock );
01612 
01613     p_view = playlist_ViewFind( p_playlist, p_intf->p_sys->i_current_view );
01614 
01615     /* First clear the old one */
01616     PlaylistDestroy( p_intf );
01617 
01618     /* Build the new one */
01619     PlaylistAddNode( p_intf, p_view->p_root, 0, "" );
01620 
01621     p_sys->b_need_update = VLC_FALSE;
01622 
01623     vlc_mutex_unlock( &p_playlist->object_lock );
01624 }
01625 
01626 static void PlaylistAddNode( intf_thread_t *p_intf, playlist_item_t *p_node,
01627                              int i, char *c )
01628 {
01629     intf_sys_t *p_sys = p_intf->p_sys;
01630     playlist_item_t *p_child;
01631     char *psz_tmp;
01632     int k;
01633 
01634     psz_tmp = (char *)malloc( strlen( c ) + 4 );
01635     if( psz_tmp == NULL ) return;
01636     for( k = 0; k < p_node->i_children; k++ )
01637     {
01638         struct pl_item_t *p_pl_item;
01639         char *buff;
01640         int i_size;
01641 
01642         p_child = p_node->pp_children[k];
01643         i_size = strlen( c ) + strlen( p_child->input.psz_name ) + 4;
01644         buff = (char *)malloc( sizeof( char ) * i_size );
01645         p_pl_item = (struct pl_item_t *)malloc( sizeof( struct pl_item_t ) );
01646         if(  p_pl_item == NULL || buff == NULL ) return;
01647 
01648         if( strlen( c ) )
01649         {
01650             sprintf( buff, "%s%c-%s", c, k == p_node->i_children - 1 ?
01651                      '`' : '|', p_child->input.psz_name );
01652         }
01653         else
01654         {
01655             sprintf( buff, " %s", p_child->input.psz_name );
01656         }
01657         p_pl_item->psz_display = strdup( buff );
01658         p_pl_item->p_item = p_child;
01659         INSERT_ELEM( p_sys->pp_plist, p_sys->i_plist_entries,
01660                      p_sys->i_plist_entries, p_pl_item );
01661         free( buff );
01662         i++;
01663 
01664         if( p_child->i_children > 0 )
01665         {
01666             sprintf( psz_tmp, "%s%c ", c,
01667                      k == p_node->i_children - 1 ? ' ' : '|' );
01668             PlaylistAddNode( p_intf, p_child, i,
01669                              strlen( c ) ? psz_tmp : " " );
01670         }
01671     }
01672     free( psz_tmp );
01673 }
01674 
01675 static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
01676                             vlc_value_t oval, vlc_value_t nval, void *param )
01677 {
01678     intf_thread_t *p_intf = (intf_thread_t *)param;
01679     p_intf->p_sys->b_need_update = VLC_TRUE;
01680     return VLC_SUCCESS;
01681 }
01682 
01683 static void FindIndex( intf_thread_t *p_intf )
01684 {
01685     intf_sys_t *p_sys = p_intf->p_sys;
01686     int i;
01687 
01688     if( p_sys->i_current_view == VIEW_ALL )
01689     {
01690          p_sys->i_box_plidx = p_sys->p_playlist->i_index;
01691     }
01692     else if( ( p_sys->i_box_plidx < p_sys->i_plist_entries &&
01693                p_sys->pp_plist[p_sys->i_box_plidx]->p_item !=
01694                p_sys->p_playlist->status.p_item ) )
01695     {
01696         for( i = 0; i < p_sys->i_plist_entries; i++ )
01697         {
01698             if( p_sys->pp_plist[i]->p_item ==
01699                 p_sys->p_playlist->status.p_item )
01700             {
01701                 p_sys->i_box_plidx = i;
01702                 break;
01703             }
01704         }
01705     }
01706 }
01707 
01708 static void PlaylistDestroy( intf_thread_t *p_intf )
01709 {
01710     intf_sys_t *p_sys = p_intf->p_sys;
01711     int i;
01712 
01713     for( i = 0; i < p_sys->i_plist_entries; i++ )
01714     {
01715         struct pl_item_t *p_pl_item = p_sys->pp_plist[i];
01716         free( p_pl_item->psz_display );
01717         REMOVE_ELEM( p_sys->pp_plist, p_sys->i_plist_entries, i );
01718         free( p_pl_item );
01719     }
01720     p_sys->pp_plist = NULL;
01721     p_sys->i_plist_entries = 0;
01722 }
01723 
01724 static void Eject( intf_thread_t *p_intf )
01725 {
01726     char *psz_device = NULL, *psz_parser, *psz_name;
01727 
01728     /*
01729      * Get the active input
01730      * Determine whether we can eject a media, ie it's a DVD, VCD or CD-DA
01731      * If it's neither of these, then return
01732      */
01733 
01734     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
01735                                                        FIND_ANYWHERE );
01736 
01737     if( p_playlist == NULL )
01738     {
01739         return;
01740     }
01741 
01742     vlc_mutex_lock( &p_playlist->object_lock );
01743 
01744     if( p_playlist->i_index < 0 )
01745     {
01746         vlc_mutex_unlock( &p_playlist->object_lock );
01747         vlc_object_release( p_playlist );
01748         return;
01749     }
01750 
01751     psz_name = p_playlist->pp_items[ p_playlist->i_index ]->input.psz_name;
01752 
01753     if( psz_name )
01754     {
01755         if( !strncmp(psz_name, "dvd://", 4) )
01756         {
01757             switch( psz_name[strlen("dvd://")] )
01758             {
01759             case '\0':
01760             case '@':
01761                 psz_device = config_GetPsz( p_intf, "dvd" );
01762                 break;
01763             default:
01764                 /* Omit the first MRL-selector characters */
01765                 psz_device = strdup( psz_name + strlen("dvd://" ) );
01766                 break;
01767             }
01768         }
01769         else if( !strncmp(psz_name, VCD_MRL, strlen(VCD_MRL)) )
01770         {
01771             switch( psz_name[strlen(VCD_MRL)] )
01772             {
01773             case '\0':
01774             case '@':
01775                 psz_device = config_GetPsz( p_intf, VCD_MRL );
01776                 break;
01777             default:
01778                 /* Omit the beginning MRL-selector characters */
01779                 psz_device = strdup( psz_name + strlen(VCD_MRL) );
01780                 break;
01781             }
01782         }
01783         else if( !strncmp(psz_name, CDDA_MRL, strlen(CDDA_MRL) ) )
01784         {
01785             switch( psz_name[strlen(CDDA_MRL)] )
01786             {
01787             case '\0':
01788             case '@':
01789                 psz_device = config_GetPsz( p_intf, "cd-audio" );
01790                 break;
01791             default:
01792                 /* Omit the beginning MRL-selector characters */
01793                 psz_device = strdup( psz_name + strlen(CDDA_MRL) );
01794                 break;
01795             }
01796         }
01797         else
01798         {
01799             psz_device = strdup( psz_name );
01800         }
01801     }
01802 
01803     vlc_mutex_unlock( &p_playlist->object_lock );
01804     vlc_object_release( p_playlist );
01805 
01806     if( psz_device == NULL )
01807     {
01808         return;
01809     }
01810 
01811     /* Remove what we have after @ */
01812     psz_parser = psz_device;
01813     for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
01814     {
01815         if( *psz_parser == '@' )
01816         {
01817             *psz_parser = '\0';
01818             break;
01819         }
01820     }
01821 
01822     /* If there's a stream playing, we aren't allowed to eject ! */
01823     if( p_intf->p_sys->p_input == NULL )
01824     {
01825         msg_Dbg( p_intf, "ejecting %s", psz_device );
01826 
01827         intf_Eject( p_intf, psz_device );
01828     }
01829 
01830     free(psz_device);
01831     return;
01832 }
01833 
01834 static int comp_dir_entries( const void *pp_dir_entry1,
01835                              const void *pp_dir_entry2 )
01836 {
01837     struct dir_entry_t *p_dir_entry1 = *(struct dir_entry_t**)pp_dir_entry1;
01838     struct dir_entry_t *p_dir_entry2 = *(struct dir_entry_t**)pp_dir_entry2;
01839     if ( p_dir_entry1->b_file == p_dir_entry2->b_file ) {
01840         return strcasecmp( p_dir_entry1->psz_path, p_dir_entry2->psz_path );
01841     }
01842     else 
01843     {
01844         return ( p_dir_entry1->b_file ? 1 : -1 );
01845     }
01846 }
01847 
01848 static void ReadDir( intf_thread_t *p_intf )
01849 {
01850     intf_sys_t     *p_sys = p_intf->p_sys;
01851     DIR *                       p_current_dir;
01852     struct dirent *             p_dir_content;
01853     int i;
01854 
01855     if( p_sys->psz_current_dir && *p_sys->psz_current_dir )
01856     {
01857         /* Open the dir */
01858         p_current_dir = opendir( p_sys->psz_current_dir );
01859 
01860         if( p_current_dir == NULL )
01861         {
01862             /* something went bad, get out of here ! */
01863 #ifdef HAVE_ERRNO_H
01864             msg_Warn( p_intf, "cannot open directory `%s' (%s)",
01865                       p_sys->psz_current_dir, strerror(errno));
01866 #else
01867             msg_Warn( p_intf, "cannot open directory `%s'", p_sys->psz_current_dir );
01868 #endif
01869             return;
01870         }
01871 
01872         /* Clean the old shit */
01873         for( i = 0; i < p_sys->i_dir_entries; i++ )
01874         {
01875             struct dir_entry_t *p_dir_entry = p_sys->pp_dir_entries[i];
01876             free( p_dir_entry->psz_path );
01877             REMOVE_ELEM( p_sys->pp_dir_entries, p_sys->i_dir_entries, i );
01878             free( p_dir_entry );
01879         }
01880         p_sys->pp_dir_entries = NULL;
01881         p_sys->i_dir_entries = 0;
01882 
01883         /* get the first directory entry */
01884         p_dir_content = readdir( p_current_dir );
01885 
01886         /* while we still have entries in the directory */
01887         while( p_dir_content != NULL )
01888         {
01889 #if defined( S_ISDIR )
01890             struct stat stat_data;
01891 #endif
01892             struct dir_entry_t *p_dir_entry;
01893             int i_size_entry = strlen( p_sys->psz_current_dir ) +
01894                                strlen( p_dir_content->d_name ) + 2;
01895             char *psz_uri;
01896 
01897             if( p_sys->b_show_hidden_files == VLC_FALSE && 
01898                 ( strlen( p_dir_content->d_name ) &&
01899                   p_dir_content->d_name[0] == '.' ) &&
01900                 strcmp( p_dir_content->d_name, ".." ) )
01901             {
01902                 p_dir_content = readdir( p_current_dir );
01903                 continue;
01904             } 
01905 
01906             psz_uri = (char *)malloc( sizeof(char)*i_size_entry);
01907             sprintf( psz_uri, "%s/%s", p_sys->psz_current_dir,
01908                      p_dir_content->d_name );
01909 
01910             if( !( p_dir_entry = malloc( sizeof( struct dir_entry_t) ) ) )
01911             {
01912                 free( psz_uri);
01913                 return;
01914             }
01915 
01916 #if defined( S_ISDIR )
01917             stat( psz_uri, &stat_data );
01918             if( S_ISDIR(stat_data.st_mode) )
01919 #elif defined( DT_DIR )
01920             if( p_dir_content->d_type & DT_DIR )
01921 #else
01922             if( 0 )
01923 #endif
01924             {
01925                 p_dir_entry->psz_path = strdup( p_dir_content->d_name );
01926                 p_dir_entry->b_file = VLC_FALSE;
01927                 INSERT_ELEM( p_sys->pp_dir_entries, p_sys->i_dir_entries,
01928                      p_sys->i_dir_entries, p_dir_entry );
01929             }
01930             else
01931             {
01932                 p_dir_entry->psz_path = strdup( p_dir_content->d_name );
01933                 p_dir_entry->b_file = VLC_TRUE;
01934                 INSERT_ELEM( p_sys->pp_dir_entries, p_sys->i_dir_entries,
01935                      p_sys->i_dir_entries, p_dir_entry );
01936             }
01937 
01938             free( psz_uri );
01939             /* Read next entry */
01940             p_dir_content = readdir( p_current_dir );
01941         }
01942 
01943         /* Sort */
01944         qsort( p_sys->pp_dir_entries, p_sys->i_dir_entries,
01945                sizeof(struct dir_entry_t*), &comp_dir_entries );
01946 
01947         closedir( p_current_dir );
01948         return;
01949     }
01950     else
01951     {
01952         msg_Dbg( p_intf, "no current dir set" );
01953         return;
01954     }
01955 }
01956 
01957 static void PlayPause( intf_thread_t *p_intf )
01958 {
01959     input_thread_t *p_input = p_intf->p_sys->p_input;
01960     vlc_value_t val;
01961 
01962     if( p_input )
01963     {
01964         var_Get( p_input, "state", &val );
01965         if( val.i_int != PAUSE_S )
01966         {
01967             val.i_int = PAUSE_S;
01968         }
01969         else
01970         {
01971             val.i_int = PLAYING_S;
01972         }
01973         var_Set( p_input, "state", val );
01974     }
01975     else if( p_intf->p_sys->p_playlist )
01976     {
01977         playlist_Play( p_intf->p_sys->p_playlist );
01978     }
01979 }
01980 
01981 /****************************************************************************
01982  *
01983  ****************************************************************************/
01984 static void DrawBox( WINDOW *win, int y, int x, int h, int w, char *title )
01985 {
01986     int i;
01987     int i_len;
01988 
01989     if( w > 3 && h > 2 )
01990     {
01991         if( title == NULL ) title = "";
01992         i_len = strlen( title );
01993 
01994         if( i_len > w - 2 ) i_len = w - 2;
01995 
01996         mvwaddch( win, y, x,    ACS_ULCORNER );
01997         mvwhline( win, y, x+1,  ACS_HLINE, ( w-i_len-2)/2 );
01998         mvwprintw( win,y, x+1+(w-i_len-2)/2, "%s", title );
01999         mvwhline( win, y, x+(w-i_len)/2+i_len,  ACS_HLINE, w - 1 - ((w-i_len)/2+i_len) );
02000         mvwaddch( win, y, x+w-1,ACS_URCORNER );
02001 
02002         for( i = 0; i < h-2; i++ )
02003         {
02004             mvwaddch( win, y+i+1, x,     ACS_VLINE );
02005             mvwaddch( win, y+i+1, x+w-1, ACS_VLINE );
02006         }
02007 
02008         mvwaddch( win, y+h-1, x,     ACS_LLCORNER );
02009         mvwhline( win, y+h-1, x+1,   ACS_HLINE, w - 2 );
02010         mvwaddch( win, y+h-1, x+w-1, ACS_LRCORNER );
02011     }
02012 }
02013 
02014 static void DrawEmptyLine( WINDOW *win, int y, int x, int w )
02015 {
02016     if( w > 0 )
02017     {
02018         mvhline( y, x, ' ', w );
02019     }
02020 }
02021 
02022 static void DrawLine( WINDOW *win, int y, int x, int w )
02023 {
02024     if( w > 0 )
02025     {
02026         attrset( A_REVERSE );
02027         mvhline( y, x, ' ', w );
02028         attroff( A_REVERSE );
02029     }
02030 }

Generated on Tue Dec 20 10:14:39 2005 for vlc-0.8.4a by  doxygen 1.4.2