79943447a2b8b35a4e1df2e42fb62d0a9f37aaeb
[vlc.git] / modules / gui / wxwindows / interface.cpp
1 /*****************************************************************************
2  * interface.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: interface.cpp,v 1.16 2003/03/26 00:56:22 gbazin Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31
32 #include <vlc/vlc.h>
33
34 #ifdef WIN32                                                 /* mingw32 hack */
35 #undef Yield
36 #undef CreateDialog
37 #endif
38
39 /* Let vlc take care of the i18n stuff */
40 #define WXINTL_NO_GETTEXT_MACRO
41
42 #include <wx/wxprec.h>
43 #include <wx/wx.h>
44
45 #include <vlc/intf.h>
46 #include "stream_control.h"
47
48 #include "wxwindows.h"
49
50 /* include the toolbar graphics */
51 #include "bitmaps/file.xpm"
52 #include "bitmaps/disc.xpm"
53 #include "bitmaps/net.xpm"
54 #if 0
55 #include "bitmaps/sat.xpm"
56 #endif
57 #include "bitmaps/play.xpm"
58 #include "bitmaps/pause.xpm"
59 #include "bitmaps/stop.xpm"
60 #include "bitmaps/previous.xpm"
61 #include "bitmaps/next.xpm"
62 #include "bitmaps/playlist.xpm"
63 #define TOOLBAR_BMP_WIDTH 24
64 #define TOOLBAR_BMP_HEIGHT 24
65
66 /* include the icon graphic */
67 #include "share/vlc32x32.xpm"
68
69 /*****************************************************************************
70  * Local class declarations.
71  *****************************************************************************/
72
73 /*****************************************************************************
74  * Event Table.
75  *****************************************************************************/
76
77 /* IDs for the controls and the menu commands */
78 enum
79 {
80     /* menu items */
81     Exit_Event = wxID_HIGHEST,
82     OpenFile_Event,
83     OpenDisc_Event,
84     OpenNet_Event,
85     OpenSat_Event,
86     EjectDisc_Event,
87
88     Playlist_Event,
89     Logs_Event,
90     FileInfo_Event,
91
92     Audio_Event,
93     Subtitles_Event,
94     Prefs_Event,
95
96     SliderScroll_Event,
97     StopStream_Event,
98     PlayStream_Event,
99     PrevStream_Event,
100     NextStream_Event,
101
102     /* it is important for the id corresponding to the "About" command to have
103      * this standard value as otherwise it won't be handled properly under Mac
104      * (where it is special and put into the "Apple" menu) */
105     About_Event = wxID_ABOUT
106 };
107
108 BEGIN_EVENT_TABLE(Interface, wxFrame)
109     /* Menu events */
110     EVT_MENU(Exit_Event, Interface::OnExit)
111     EVT_MENU(About_Event, Interface::OnAbout)
112     EVT_MENU(Playlist_Event, Interface::OnPlaylist)
113     EVT_MENU(Logs_Event, Interface::OnLogs)
114     EVT_MENU(FileInfo_Event, Interface::OnFileInfo)
115     EVT_MENU(Prefs_Event, Interface::OnPreferences)
116
117     /* Toolbar events */
118     EVT_MENU(OpenFile_Event, Interface::OnOpenFile)
119     EVT_MENU(OpenDisc_Event, Interface::OnOpenDisc)
120     EVT_MENU(OpenNet_Event, Interface::OnOpenNet)
121     EVT_MENU(OpenSat_Event, Interface::OnOpenSat)
122     EVT_MENU(StopStream_Event, Interface::OnStopStream)
123     EVT_MENU(PlayStream_Event, Interface::OnPlayStream)
124     EVT_MENU(PrevStream_Event, Interface::OnPrevStream)
125     EVT_MENU(NextStream_Event, Interface::OnNextStream)
126
127     /* Slider events */
128     EVT_COMMAND_SCROLL(SliderScroll_Event, Interface::OnSliderUpdate)
129 END_EVENT_TABLE()
130
131 /*****************************************************************************
132  * Constructor.
133  *****************************************************************************/
134 Interface::Interface( intf_thread_t *_p_intf ):
135     wxFrame( NULL, -1, VOUT_TITLE,
136              wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE )
137 {
138     /* Initializations */
139     p_intf = _p_intf;
140     p_prefs_dialog = NULL;
141     p_fileinfo_window = NULL;
142     i_old_playing_status = PAUSE_S;
143
144     /* Give our interface a nice little icon */
145     SetIcon( *new wxIcon( vlc_xpm ) );
146
147     /* Create a sizer for the main frame */
148     frame_sizer = new wxBoxSizer( wxHORIZONTAL );
149     SetSizer( frame_sizer );
150
151     /* Creation of the menu bar */
152     CreateOurMenuBar();
153
154     /* Creation of the tool bar */
155     CreateOurToolBar();
156
157     /* Creation of the slider sub-window */
158     CreateOurSlider();
159
160     /* Creation of the status bar
161      * Helptext for menu items and toolbar tools will automatically get
162      * displayed here. */
163     int i_status_width[2] = {-2,-3};
164     statusbar = CreateStatusBar( 2 );                            /* 2 fields */
165     statusbar->SetStatusWidths( 2, i_status_width );
166
167     /* Make sure we've got the right background colour */
168     SetBackgroundColour( slider_frame->GetBackgroundColour() );
169
170     /* Layout everything */
171     SetAutoLayout( TRUE );
172     frame_sizer->Layout();
173     frame_sizer->Fit(this);
174
175 #if !defined(__WXX11__)
176     /* Associate drop targets with the main interface */
177     SetDropTarget( new DragAndDrop( p_intf ) );
178 #endif
179 }
180
181 Interface::~Interface()
182 {
183     if( p_prefs_dialog ) p_prefs_dialog->Destroy();
184     if( p_fileinfo_window ) p_fileinfo_window->Destroy();
185 }
186
187 /*****************************************************************************
188  * Private methods.
189  *****************************************************************************/
190 void Interface::CreateOurMenuBar()
191 {
192 #define HELP_FILE  N_("Open a file")
193 #define HELP_DISC  N_("Open a DVD or (S)VCD")
194 #define HELP_NET   N_("Open a network stream")
195 #define HELP_SAT   N_("Open a satellite stream")
196 #define HELP_EJECT N_("Eject the DVD/CD")
197 #define HELP_EXIT  N_("Exit this program")
198
199 #define HELP_PLAYLIST   N_("Open the playlist")
200 #define HELP_LOGS       N_("Show the program logs")
201 #define HELP_FILEINFO       N_("Show information about the file being played")
202
203 #define HELP_AUDIO N_("Change the current audio track")
204 #define HELP_SUBS  N_("Change the current subtitles stream")
205 #define HELP_PREFS N_("Go to the preferences menu")
206
207 #define HELP_ABOUT N_("About this program")
208
209     /* Create the "File" menu */
210     wxMenu *file_menu = new wxMenu;
211     file_menu->Append( OpenFile_Event, _("&Open File..."), HELP_FILE );
212     file_menu->Append( OpenDisc_Event, _("Open &Disc..."), HELP_DISC );
213     file_menu->Append( OpenNet_Event, _("&Network Stream..."), HELP_NET );
214 #if 0
215     file_menu->Append( OpenSat_Event, _("&Satellite Stream..."), HELP_NET );
216 #endif
217     file_menu->AppendSeparator();
218     file_menu->Append( EjectDisc_Event, _("&Eject Disc"), HELP_EJECT );
219     file_menu->AppendSeparator();
220     file_menu->Append( Exit_Event, _("E&xit"), HELP_EXIT );
221
222     /* Create the "View" menu */
223     wxMenu *view_menu = new wxMenu;
224     view_menu->Append( Playlist_Event, _("&Playlist..."), HELP_PLAYLIST );
225     view_menu->Append( Logs_Event, _("&Logs..."), HELP_LOGS );
226     view_menu->Append( FileInfo_Event, _("&File info..."), HELP_FILEINFO );
227
228     /* Create the "Settings" menu */
229     wxMenu *settings_menu = new wxMenu;
230     settings_menu->Append( Audio_Event, _("&Audio"), HELP_AUDIO );
231     settings_menu->Append( Subtitles_Event, _("&Subtitles"), HELP_SUBS );
232     settings_menu->AppendSeparator();
233     settings_menu->Append( Prefs_Event, _("&Preferences..."), HELP_PREFS );
234
235     /* Create the "Help" menu */
236     wxMenu *help_menu = new wxMenu;
237     help_menu->Append( About_Event, _("&About..."), HELP_ABOUT );
238
239     /* Append the freshly created menus to the menu bar... */
240     wxMenuBar *menubar = new wxMenuBar( wxMB_DOCKABLE );
241     menubar->Append( file_menu, _("&File") );
242     menubar->Append( view_menu, _("&View") );
243     menubar->Append( settings_menu, _("&Settings") );
244     menubar->Append( help_menu, _("&Help") );
245
246     /* Attach the menu bar to the frame */
247     SetMenuBar( menubar );
248
249 #if !defined(__WXX11__)
250     /* Associate drop targets with the menubar */
251     menubar->SetDropTarget( new DragAndDrop( p_intf ) );
252 #endif
253 }
254
255 void Interface::CreateOurToolBar()
256 {
257 #define HELP_STOP N_("Stop current playlist item")
258 #define HELP_PLAY N_("Play current playlist item")
259 #define HELP_PAUSE N_("Pause current playlist item")
260 #define HELP_PLO N_("Open playlist")
261 #define HELP_PLP N_("Previous playlist item")
262 #define HELP_PLN N_("Next playlist item")
263
264     wxLogNull LogDummy; /* Hack to suppress annoying log message on the win32
265                          * version because we don't include wx.rc */
266
267     wxToolBar *toolbar = CreateToolBar(
268         wxTB_HORIZONTAL | wxTB_TEXT | wxTB_FLAT | wxTB_DOCKABLE );
269
270     toolbar->SetToolBitmapSize( wxSize(TOOLBAR_BMP_WIDTH,TOOLBAR_BMP_HEIGHT) );
271
272     toolbar->AddTool( OpenFile_Event, _("File"), wxBitmap( file_xpm ),
273                       HELP_FILE );
274     toolbar->AddTool( OpenDisc_Event, _("Disc"), wxBitmap( disc_xpm ),
275                       HELP_DISC );
276     toolbar->AddTool( OpenNet_Event, _("Net"), wxBitmap( net_xpm ),
277                       HELP_NET );
278 #if 0
279     toolbar->AddTool( OpenSat_Event, _("Sat"), wxBitmap( sat_xpm ),
280                       HELP_SAT );
281 #endif
282     toolbar->AddSeparator();
283     toolbar->AddTool( StopStream_Event, _("Stop"), wxBitmap( stop_xpm ),
284                       HELP_STOP );
285     toolbar->AddTool( PlayStream_Event, _("Play"), wxBitmap( play_xpm ),
286                       HELP_PLAY );
287     toolbar->AddSeparator();
288     toolbar->AddTool( Playlist_Event, _("Playlist"), wxBitmap( playlist_xpm ),
289                       HELP_PLO );
290     toolbar->AddTool( PrevStream_Event, _("Prev"), wxBitmap( previous_xpm ),
291                       HELP_PLP );
292     toolbar->AddTool( NextStream_Event, _("Next"), wxBitmap( next_xpm ),
293                       HELP_PLN );
294
295     toolbar->Realize();
296
297     /* Place the toolbar in a sizer, so we can calculate the width of the
298      * toolbar and set this as the minimum for the main frame size. */
299     wxBoxSizer *toolbar_sizer = new wxBoxSizer( wxHORIZONTAL );
300     toolbar_sizer->Add( toolbar, 0, 0, 0 );
301     toolbar_sizer->Layout();
302
303 #ifndef WIN32
304     frame_sizer->SetMinSize( toolbar_sizer->GetMinSize().GetWidth(), -1 );
305 #else
306     frame_sizer->SetMinSize( toolbar->GetToolSize().GetWidth() *
307                              toolbar->GetToolsCount(), -1 );
308 #endif
309
310 #if !defined(__WXX11__)
311     /* Associate drop targets with the toolbar */
312     toolbar->SetDropTarget( new DragAndDrop( p_intf ) );
313 #endif
314 }
315
316 void Interface::CreateOurSlider()
317 {
318     /* Create a new frame containing the slider */
319     slider_frame = new wxPanel( this, -1, wxDefaultPosition, wxDefaultSize );
320     slider_frame->SetAutoLayout( TRUE );
321     slider_frame->Hide();
322
323     /* Create static box to surround the slider */
324     slider_box = new wxStaticBox( slider_frame, -1, "" );
325
326     /* Create sizer for slider frame */
327     wxStaticBoxSizer *slider_sizer =
328         new wxStaticBoxSizer( slider_box, wxHORIZONTAL );
329     slider_frame->SetSizer( slider_sizer );
330     slider_sizer->SetMinSize( -1, 50 );
331
332     /* Create slider */
333     slider = new wxSlider( slider_frame, SliderScroll_Event, 0, 0,
334                            SLIDER_MAX_POS, wxDefaultPosition, wxDefaultSize );
335     slider_sizer->Add( slider, 1, wxGROW | wxALL, 5 );
336     slider_sizer->Layout();
337     slider_sizer->SetSizeHints(slider_frame);
338 }
339
340 void Interface::Open( int i_access_method )
341 {
342     /* Show/hide the open dialog */
343     OpenDialog dialog( p_intf, this, i_access_method );
344
345     if( dialog.ShowModal() == wxID_OK )
346     {
347         /* Update the playlist */
348         playlist_t *p_playlist =
349             (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
350                                            FIND_ANYWHERE );
351         if( p_playlist == NULL )
352         {
353             return;
354         }
355
356         msg_Err( p_intf, "%s", (char *)dialog.mrl.c_str() );
357
358         playlist_Add( p_playlist, (char *)dialog.mrl.c_str(),
359                       PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
360
361         TogglePlayButton( PLAYING_S );
362
363         /* Rebuild the playlist */
364         p_intf->p_sys->p_playlist_window->Rebuild();
365
366         vlc_object_release( p_playlist );
367     }
368 }
369
370 /*****************************************************************************
371  * Event Handlers.
372  *****************************************************************************/
373 void Interface::OnExit( wxCommandEvent& WXUNUSED(event) )
374 {
375     /* TRUE is to force the frame to close. */
376     Close(TRUE);
377 }
378
379 void Interface::OnAbout( wxCommandEvent& WXUNUSED(event) )
380 {
381     wxString msg;
382     msg.Printf( VOUT_TITLE + wxString(_(" (wxWindows interface)\n\n")) +
383         wxString(_("(C) 1996-2003 - the VideoLAN Team\n\n")) +
384         wxString(_("The VideoLAN team <videolan@videolan.org>\n"
385                    "http://www.videolan.org/\n\n")) +
386         wxString(_("This is the VideoLAN Client, a DVD, MPEG and DivX player."
387           "\nIt can play MPEG and MPEG2 files from a file or from a "
388           "network source.")) );
389
390     wxMessageBox( msg, wxString(_("About ")) + VOUT_TITLE,
391                   wxOK | wxICON_INFORMATION, this );
392 }
393
394 void Interface::OnPlaylist( wxCommandEvent& WXUNUSED(event) )
395 {
396     /* Show/hide the playlist window */
397     wxFrame *p_playlist_window = p_intf->p_sys->p_playlist_window;
398     if( p_playlist_window )
399     {
400         p_playlist_window->Show( ! p_playlist_window->IsShown() );
401     }
402 }
403
404 void Interface::OnLogs( wxCommandEvent& WXUNUSED(event) )
405 {
406     /* Show/hide the log window */
407     wxFrame *p_messages_window = p_intf->p_sys->p_messages_window;
408     if( p_messages_window )
409     {
410         p_messages_window->Show( ! p_messages_window->IsShown() );
411     }
412 }
413
414 void Interface::OnFileInfo( wxCommandEvent& WXUNUSED(event) )
415 {
416     /* Show/hide the fileinfo window */
417     if( p_fileinfo_window == NULL )
418     {
419         p_fileinfo_window = new FileInfo( p_intf, this );
420     }
421
422     if( p_fileinfo_window )
423     {
424         p_fileinfo_window->Show( true );//! p_messages_window->IsShown() );
425     }
426 }
427
428 void Interface::OnPreferences( wxCommandEvent& WXUNUSED(event) )
429 {
430     /* Show/hide the open dialog */
431     if( p_prefs_dialog == NULL )
432     {
433         p_prefs_dialog = new PrefsDialog( p_intf, this );
434     }
435
436     if( p_prefs_dialog )
437     {
438         p_prefs_dialog->Show( true );
439     }
440 }
441
442 void Interface::OnOpenFile( wxCommandEvent& WXUNUSED(event) )
443 {
444     Open( FILE_ACCESS );
445 }
446
447 void Interface::OnOpenDisc( wxCommandEvent& WXUNUSED(event) )
448 {
449     Open( DISC_ACCESS );
450 }
451
452 void Interface::OnOpenNet( wxCommandEvent& WXUNUSED(event) )
453 {
454     Open( NET_ACCESS );
455 }
456
457 void Interface::OnOpenSat( wxCommandEvent& WXUNUSED(event) )
458 {
459     Open( SAT_ACCESS );
460 }
461
462 void Interface::OnPlayStream( wxCommandEvent& WXUNUSED(event) )
463 {
464     wxCommandEvent dummy;
465     playlist_t *p_playlist =
466         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
467                                        FIND_ANYWHERE );
468     if( p_playlist == NULL )
469     {
470         /* If the playlist is empty, open a file requester instead */
471         OnOpenFile( dummy );
472         return;
473     }
474
475     vlc_mutex_lock( &p_playlist->object_lock );
476     if( p_playlist->i_size )
477     {
478         vlc_mutex_unlock( &p_playlist->object_lock );
479
480         input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf,
481                                                        VLC_OBJECT_INPUT,
482                                                        FIND_ANYWHERE );
483         if( p_input == NULL )
484         {
485             /* No stream was playing, start one */
486             playlist_Play( p_playlist );
487             TogglePlayButton( PLAYING_S );
488             vlc_object_release( p_playlist );
489             return;
490         }
491
492         if( p_input->stream.control.i_status != PAUSE_S )
493         {
494             /* A stream is being played, pause it */
495             input_SetStatus( p_input, INPUT_STATUS_PAUSE );
496             TogglePlayButton( PAUSE_S );
497             vlc_object_release( p_playlist );
498             vlc_object_release( p_input );
499             return;
500         }
501
502         /* Stream is paused, resume it */
503         playlist_Play( p_playlist );
504         TogglePlayButton( PLAYING_S );
505         vlc_object_release( p_input );
506         vlc_object_release( p_playlist );
507     }
508     else
509     {
510         vlc_mutex_unlock( &p_playlist->object_lock );
511         vlc_object_release( p_playlist );
512         OnOpenFile( dummy );
513     }
514 }
515
516 void Interface::OnStopStream( wxCommandEvent& WXUNUSED(event) )
517 {
518     playlist_t * p_playlist =
519         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
520                                        FIND_ANYWHERE );
521     if( p_playlist == NULL )
522     {
523         return;
524     }
525
526     playlist_Stop( p_playlist );
527     TogglePlayButton( PAUSE_S );
528     vlc_object_release( p_playlist );
529 }
530
531 void Interface::OnSliderUpdate( wxScrollEvent& event )
532 {
533     vlc_mutex_lock( &p_intf->change_lock );
534
535 #ifdef WIN32
536     if( event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
537         || event.GetEventType() == wxEVT_SCROLL_ENDSCROLL )
538     {
539 #endif
540         if( p_intf->p_sys->i_slider_pos != event.GetPosition()
541             && p_intf->p_sys->p_input )
542         {
543             p_intf->p_sys->i_slider_pos = event.GetPosition();
544             input_Seek( p_intf->p_sys->p_input, p_intf->p_sys->i_slider_pos *
545                         100 / SLIDER_MAX_POS,
546                         INPUT_SEEK_PERCENT | INPUT_SEEK_SET );
547         }
548
549 #ifdef WIN32
550         p_intf->p_sys->b_slider_free = VLC_TRUE;
551     }
552     else
553     {
554         p_intf->p_sys->b_slider_free = VLC_FALSE;
555
556         if( p_intf->p_sys->p_input )
557         {
558             /* Update stream date */
559 #define p_area p_intf->p_sys->p_input->stream.p_selected_area
560             char psz_time[ OFFSETTOTIME_MAX_SIZE ];
561
562             slider_box->SetLabel(
563                 input_OffsetToTime( p_intf->p_sys->p_input,
564                                     psz_time,
565                                     p_area->i_size * event.GetPosition()
566                                     / SLIDER_MAX_POS ) );
567 #undef p_area
568         }
569     }
570 #endif
571
572     vlc_mutex_unlock( &p_intf->change_lock );
573 }
574
575 void Interface::OnPrevStream( wxCommandEvent& WXUNUSED(event) )
576 {
577     playlist_t * p_playlist =
578         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
579                                        FIND_ANYWHERE );
580     if( p_playlist == NULL )
581     {
582         return;
583     }
584
585     playlist_Prev( p_playlist );
586     vlc_object_release( p_playlist );
587 }
588
589 void Interface::OnNextStream( wxCommandEvent& WXUNUSED(event) )
590 {
591     playlist_t * p_playlist =
592         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
593                                        FIND_ANYWHERE );
594     if( p_playlist == NULL )
595     {
596         return;
597     }
598
599     playlist_Next( p_playlist );
600     vlc_object_release( p_playlist );
601 }
602
603 void Interface::TogglePlayButton( int i_playing_status )
604 {
605     if( i_playing_status == i_old_playing_status )
606         return;
607
608     GetToolBar()->DeleteTool( PlayStream_Event );
609
610     if( i_playing_status == PLAYING_S )
611     {
612         GetToolBar()->InsertTool( 5, PlayStream_Event, _("Pause"),
613                                   wxBitmap( pause_xpm ) );
614     }
615     else
616     {
617         GetToolBar()->InsertTool( 5, PlayStream_Event, _("Play"),
618                                   wxBitmap( play_xpm ) );
619     }
620
621     GetToolBar()->Realize();
622
623     i_old_playing_status = i_playing_status;
624 }
625
626 #if !defined(__WXX11__)
627 /*****************************************************************************
628  * Definition of DragAndDrop class.
629  *****************************************************************************/
630 DragAndDrop::DragAndDrop( intf_thread_t *_p_intf )
631 {
632     p_intf = _p_intf;
633 }
634
635 bool DragAndDrop::OnDropFiles( wxCoord, wxCoord,
636                                const wxArrayString& filenames )
637 {
638     unsigned int i;
639
640     /* Add dropped files to the playlist */
641
642     playlist_t *p_playlist =
643         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
644                                        FIND_ANYWHERE );
645     if( p_playlist == NULL )
646     {
647         return FALSE;
648     }
649
650     for( i = 0; i < filenames.GetCount(); i++ )
651         playlist_Add( p_playlist, (char *)filenames[i].c_str(),
652                       PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
653
654     /* Rebuild the playlist */
655     p_intf->p_sys->p_playlist_window->Rebuild();
656
657     vlc_object_release( p_playlist );
658
659     return TRUE;
660 }
661 #endif