]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/playlist.cpp
6038da371d472927904bdcc1cc84ae6aee5d4f75
[vlc] / modules / gui / wxwindows / playlist.cpp
1 /*****************************************************************************
2  * playlist.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: playlist.cpp,v 1.22 2003/10/06 16:23:30 zorglub Exp $
6  *
7  * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
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 #include <vlc/intf.h>
34
35 #include "wxwindows.h"
36 #include <wx/listctrl.h>
37
38 /* Callback prototype */
39 int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
40                      vlc_value_t old_val, vlc_value_t new_val, void *param );
41
42 /*****************************************************************************
43  * Event Table.
44  *****************************************************************************/
45
46 /* IDs for the controls and the menu commands */
47 enum
48 {
49     /* menu items */
50     AddFile_Event = 1,
51     AddMRL_Event,
52     Sort_Event,
53     RSort_Event,
54     Close_Event,
55     Open_Event,
56     Save_Event,
57
58     EnableSelection_Event,
59     DisableSelection_Event,
60
61     InvertSelection_Event,
62     DeleteSelection_Event,
63     Random_Event,
64     Loop_Event,
65     Repeat_Event,
66     SelectAll_Event,
67
68     En_Dis_Event,
69
70     Infos_Event,
71
72     SearchText_Event,
73     Search_Event,
74
75     /* controls */
76     ListView_Event
77 };
78
79 BEGIN_EVENT_TABLE(Playlist, wxFrame)
80     /* Menu events */
81     EVT_MENU(AddFile_Event, Playlist::OnAddFile)
82     EVT_MENU(AddMRL_Event, Playlist::OnAddMRL)
83     EVT_MENU(Sort_Event, Playlist::OnSort)
84     EVT_MENU(RSort_Event, Playlist::OnRSort)
85     EVT_MENU(Close_Event, Playlist::OnClose)
86     EVT_MENU(Open_Event, Playlist::OnOpen)
87     EVT_MENU(Save_Event, Playlist::OnSave)
88     EVT_MENU(EnableSelection_Event, Playlist::OnEnableSelection)
89     EVT_MENU(DisableSelection_Event, Playlist::OnDisableSelection)
90     EVT_MENU(InvertSelection_Event, Playlist::OnInvertSelection)
91     EVT_MENU(DeleteSelection_Event, Playlist::OnDeleteSelection)
92     EVT_MENU(SelectAll_Event, Playlist::OnSelectAll)
93     EVT_MENU(Infos_Event, Playlist::OnInfos)
94     EVT_CHECKBOX(Random_Event, Playlist::OnRandom)
95     EVT_CHECKBOX(Repeat_Event, Playlist::OnRepeat)
96     EVT_CHECKBOX(Loop_Event, Playlist::OnLoop)
97
98     /* Listview events */
99     EVT_LIST_ITEM_ACTIVATED(ListView_Event, Playlist::OnActivateItem)
100     EVT_LIST_KEY_DOWN(ListView_Event, Playlist::OnKeyDown)
101
102     /* Button events */
103     EVT_BUTTON( Search_Event, Playlist::OnSearch)
104     EVT_BUTTON( En_Dis_Event, Playlist::OnEnDis)
105     EVT_BUTTON( Save_Event, Playlist::OnSave)
106     EVT_BUTTON( Infos_Event, Playlist::OnInfos)
107
108     EVT_TEXT(SearchText_Event, Playlist::OnSearchTextChange)
109
110     /* Special events : we don't want to destroy the window when the user
111      * clicks on (X) */
112     EVT_CLOSE(Playlist::OnClose)
113 END_EVENT_TABLE()
114
115 /*****************************************************************************
116  * Constructor.
117  *****************************************************************************/
118 Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ):
119     wxFrame( p_parent, -1, wxU(_("Playlist")), wxDefaultPosition,
120              wxDefaultSize, wxDEFAULT_FRAME_STYLE )
121 {
122     /* Initializations */
123     iteminfo_dialog = NULL;
124     p_intf = _p_intf;
125     vlc_value_t  val;
126     i_update_counter = 0;
127     b_need_update = VLC_FALSE;
128     vlc_mutex_init( p_intf, &lock );
129     SetIcon( *p_intf->p_sys->p_icon );
130
131     var_Create( p_intf, "random", VLC_VAR_BOOL );
132     var_Change( p_intf, "random", VLC_VAR_INHERITVALUE, & val, NULL );
133     var_Create( p_intf, "loop", VLC_VAR_BOOL );
134     var_Create( p_intf, "loop", VLC_VAR_BOOL );
135     var_Change( p_intf, "repeat", VLC_VAR_INHERITVALUE, & val, NULL );
136     var_Change( p_intf, "repeat", VLC_VAR_INHERITVALUE, & val, NULL );
137
138     /* Create our "Manage" menu */
139     wxMenu *manage_menu = new wxMenu;
140     manage_menu->Append( AddFile_Event, wxU(_("&Simple Add...")) );
141     manage_menu->Append( AddMRL_Event, wxU(_("&Add MRL...")) );
142     manage_menu->Append( Sort_Event, wxU(_("&Sort")) );
143     manage_menu->Append( RSort_Event, wxU(_("&Reverse Sort")) );
144     manage_menu->Append( Open_Event, wxU(_("&Open Playlist...")) );
145     manage_menu->Append( Save_Event, wxU(_("&Save Playlist...")) );
146     manage_menu->AppendSeparator();
147     manage_menu->Append( Close_Event, wxU(_("&Close")) );
148
149     /* Create our "Selection" menu */
150     wxMenu *selection_menu = new wxMenu;
151     selection_menu->Append( EnableSelection_Event, wxU(_("&Enable")) );
152     selection_menu->Append( DisableSelection_Event, wxU(_("&Disable")) );
153     selection_menu->AppendSeparator();
154     selection_menu->Append( InvertSelection_Event, wxU(_("&Invert")) );
155     selection_menu->Append( DeleteSelection_Event, wxU(_("&Delete")) );
156     selection_menu->Append( SelectAll_Event, wxU(_("&Select All")) );
157
158     /* Append the freshly created menus to the menu bar */
159     wxMenuBar *menubar = new wxMenuBar( wxMB_DOCKABLE );
160     menubar->Append( manage_menu, wxU(_("&Manage")) );
161     menubar->Append( selection_menu, wxU(_("&Selection")) );
162
163     /* Attach the menu bar to the frame */
164     SetMenuBar( menubar );
165
166     /* Create a panel to put everything in */
167     wxPanel *playlist_panel = new wxPanel( this, -1 );
168     playlist_panel->SetAutoLayout( TRUE );
169
170     /* Create the listview */
171     /* FIXME: the given size is arbitrary, and prevents us from resizing
172      * the window to smaller dimensions. But the sizers don't seem to adjust
173      * themselves to the size of a listview, and with a wxDefaultSize the
174      * playlist window is ridiculously small */
175     listview = new wxListView( playlist_panel, ListView_Event,
176                                wxDefaultPosition, wxSize( 305, 300 ),
177                                wxLC_REPORT | wxSUNKEN_BORDER );
178     listview->InsertColumn( 0, wxU(_("Url")) );
179     #if 0
180         listview->InsertColumn( 1, wxU(_("Duration")) );
181     #endif
182     listview->SetColumnWidth( 0, 300 );
183     #if 0
184         listview->SetColumnWidth( 1, 100 );
185     #endif
186
187     /* Create the Random checkbox */
188     wxCheckBox *random_checkbox =
189         new wxCheckBox( playlist_panel, Random_Event, wxU(_("Random")) );
190
191     var_Get( p_intf, "random", &val);
192     vlc_bool_t b_random = val.b_bool;
193     random_checkbox->SetValue( b_random == VLC_FALSE ? 0 : 1);
194
195     /* Create the Loop Checkbox */
196     wxCheckBox *loop_checkbox =
197         new wxCheckBox( playlist_panel, Loop_Event, wxU(_("Loop")) );
198
199     var_Get( p_intf, "loop", &val );
200     int b_loop = val.b_bool ;
201     loop_checkbox->SetValue( b_loop );
202
203     /* Create the Repeat one checkbox */
204     wxCheckBox *repeat_checkbox =
205         new wxCheckBox( playlist_panel, Repeat_Event, wxU(_("Repeat one")) );
206
207     var_Get( p_intf, "repeat", &val );
208     int b_repeat = val.b_bool ;
209     repeat_checkbox->SetValue( b_repeat );
210
211     /* Create the Search Textbox */
212     search_text =
213         new wxTextCtrl( playlist_panel, SearchText_Event, wxT(""),
214                         wxDefaultPosition, wxSize( 140, -1),
215                         wxTE_PROCESS_ENTER);
216
217     /* Create the search button */
218     search_button =
219         new wxButton( playlist_panel, Search_Event, wxU(_("Search")) );
220
221     wxButton *en_dis_button =
222         new wxButton( playlist_panel, En_Dis_Event, wxU(_("Enable/Disable Group") ) );
223
224     wxButton *iteminfo_button =
225         new wxButton( playlist_panel, Infos_Event, wxU(_("Item Infos") ) );
226     /* Place everything in sizers */
227     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
228     button_sizer->Add( en_dis_button, 0, wxALIGN_CENTER|wxRIGHT, 5);
229     button_sizer->Add( iteminfo_button, 0, wxALIGN_CENTER|wxLEFT , 5);
230     button_sizer->Layout();
231
232
233     wxBoxSizer *checkbox_sizer = new wxBoxSizer( wxHORIZONTAL );
234     checkbox_sizer->Add( random_checkbox, 0,
235                        wxEXPAND|wxALIGN_RIGHT, 5);
236     checkbox_sizer->Add( loop_checkbox, 0,
237                        wxEXPAND|wxALIGN_RIGHT, 5);
238     checkbox_sizer->Add( repeat_checkbox, 0,
239                        wxEXPAND|wxALIGN_RIGHT, 5);
240
241     checkbox_sizer->Layout();
242
243     wxBoxSizer *search_sizer = new wxBoxSizer( wxHORIZONTAL );
244     search_sizer->Add( search_text, 0, wxALL|wxALIGN_CENTER, 5);
245     search_sizer->Add( search_button, 0, wxALL|wxALIGN_CENTER, 5);
246
247     search_sizer->Layout();
248
249     wxBoxSizer *bottom_sizer = new wxBoxSizer( wxVERTICAL );
250     bottom_sizer->Add( checkbox_sizer, 0, wxALL|wxALIGN_CENTER, 5 );
251     bottom_sizer->Add( button_sizer , 0, wxALL|wxALIGN_CENTER, 5 );
252
253     bottom_sizer->Layout();
254
255     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
256
257     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
258     panel_sizer->Add( listview, 1, wxEXPAND | wxALL, 5 );
259
260     panel_sizer->Add( search_sizer, 0, wxALIGN_CENTRE );
261     panel_sizer->Add( bottom_sizer, 0 , wxALIGN_CENTRE);
262     panel_sizer->Layout();
263
264     playlist_panel->SetSizerAndFit( panel_sizer );
265     main_sizer->Add( playlist_panel, 1, wxGROW, 0 );
266     main_sizer->Layout();
267     SetSizerAndFit( main_sizer );
268
269 #if !defined(__WXX11__)
270     /* Associate drop targets with the playlist */
271     SetDropTarget( new DragAndDrop( p_intf ) );
272 #endif
273
274     playlist_t *p_playlist =
275         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
276                                        FIND_ANYWHERE );
277     if( p_playlist == NULL )
278     {
279         return;
280     }
281
282     /* We want to be noticed of playlit changes */
283     var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this );
284     vlc_object_release( p_playlist );
285
286     /* Update the playlist */
287     Rebuild();
288 }
289
290 Playlist::~Playlist()
291 {
292     playlist_t *p_playlist =
293         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
294                                        FIND_ANYWHERE );
295     if( p_playlist == NULL )
296     {
297         return;
298     }
299
300     delete iteminfo_dialog;
301
302     var_DelCallback( p_playlist, "intf-change", PlaylistChanged, this );
303     vlc_object_release( p_playlist );
304 }
305
306 void Playlist::Rebuild()
307 {
308     playlist_t *p_playlist =
309         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
310                                        FIND_ANYWHERE );
311     if( p_playlist == NULL )
312     {
313         return;
314     }
315
316     /* Clear the list... */
317     listview->DeleteAllItems();
318
319     /* ...and rebuild it */
320     vlc_mutex_lock( &p_playlist->object_lock );
321     for( int i = 0; i < p_playlist->i_size; i++ )
322     {
323         wxString filename = wxU(p_playlist->pp_items[i]->psz_name);
324         listview->InsertItem( i, filename );
325         if( p_playlist->pp_items[i]->b_enabled == VLC_FALSE )
326         {
327             wxListItem listitem;
328             listitem.m_itemId = i;
329             listitem.SetTextColour( *wxLIGHT_GREY);
330             listview->SetItem(listitem);
331         }
332         /* FIXME: we should try to find the actual duration... */
333         /* While we don't use it, hide it, it's ugly */
334         #if 0
335             listview->SetItem( i, 1, wxU(_("no info")) );
336         #endif
337     }
338     vlc_mutex_unlock( &p_playlist->object_lock );
339
340     /* Change the colour for the currenty played stream */
341     wxListItem listitem;
342     listitem.m_itemId = p_playlist->i_index;
343     listitem.SetTextColour( *wxRED );
344     listview->SetItem( listitem );
345
346     listview->Focus( p_playlist->i_index );
347
348     vlc_object_release( p_playlist );
349 }
350
351 void Playlist::ShowPlaylist( bool show )
352 {
353     if( show ) Rebuild();
354     Show( show );
355 }
356
357 void Playlist::UpdatePlaylist()
358 {
359     vlc_bool_t b_need_update = VLC_FALSE;
360     i_update_counter++;
361
362     /* If the playlist isn't show there's no need to update it */
363     if( !IsShown() ) return;
364
365     vlc_mutex_lock( &lock );
366     if( this->b_need_update )
367     {
368         b_need_update = VLC_TRUE;
369         this->b_need_update = VLC_FALSE;
370     }
371     vlc_mutex_unlock( &lock );
372
373     if( b_need_update ) Rebuild();
374
375     /* Updating the playing status every 0.5s is enough */
376     if( i_update_counter % 5 ) return;
377
378     playlist_t *p_playlist =
379         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
380                                        FIND_ANYWHERE );
381     if( p_playlist == NULL )
382     {
383         return;
384     }
385
386     /* Update the colour of items */
387     vlc_mutex_lock( &p_playlist->object_lock );
388     if( p_intf->p_sys->i_playing != p_playlist->i_index )
389     {
390         wxListItem listitem;
391         listitem.m_itemId = p_playlist->i_index;
392         listitem.SetTextColour( *wxRED );
393         listview->SetItem( listitem );
394
395         if( p_intf->p_sys->i_playing != -1 )
396         {
397             listitem.m_itemId = p_intf->p_sys->i_playing;
398             listitem.SetTextColour( *wxBLACK );
399             listview->SetItem( listitem );
400         }
401         p_intf->p_sys->i_playing = p_playlist->i_index;
402     }
403     vlc_mutex_unlock( &p_playlist->object_lock );
404
405     vlc_object_release( p_playlist );
406 }
407
408 /*****************************************************************************
409  * Private methods.
410  *****************************************************************************/
411 void Playlist::DeleteItem( int item )
412 {
413     playlist_t *p_playlist =
414         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
415                                        FIND_ANYWHERE );
416     if( p_playlist == NULL )
417     {
418         return;
419     }
420
421     playlist_Delete( p_playlist, item );
422     listview->DeleteItem( item );
423
424     vlc_object_release( p_playlist );
425 }
426
427 void Playlist::OnClose( wxCommandEvent& WXUNUSED(event) )
428 {
429     Hide();
430 }
431
432 void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) )
433 {
434     playlist_t *p_playlist =
435         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
436                                        FIND_ANYWHERE );
437     if( p_playlist == NULL )
438     {
439         return;
440     }
441
442     wxFileDialog dialog( this, wxU(_("Save playlist")),
443                          wxT(""), wxT(""), wxT("*"), wxSAVE );
444
445     if( dialog.ShowModal() == wxID_OK )
446     {
447         playlist_SaveFile( p_playlist, dialog.GetPath().mb_str() );
448     }
449
450     vlc_object_release( p_playlist );
451 }
452
453 void Playlist::OnOpen( wxCommandEvent& WXUNUSED(event) )
454 {
455     playlist_t *p_playlist =
456         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
457                                        FIND_ANYWHERE );
458     if( p_playlist == NULL )
459     {
460         return;
461     }
462
463     wxFileDialog dialog( this, wxU(_("Open playlist")),
464                          wxT(""), wxT(""), wxT("*"), wxOPEN );
465
466     if( dialog.ShowModal() == wxID_OK )
467     {
468         playlist_LoadFile( p_playlist, dialog.GetPath().mb_str() );
469     }
470
471     vlc_object_release( p_playlist );
472 }
473
474 void Playlist::OnAddFile( wxCommandEvent& WXUNUSED(event) )
475 {
476     p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_SIMPLE, 0, 0 );
477
478 #if 0
479     Rebuild();
480 #endif
481 }
482
483 void Playlist::OnAddMRL( wxCommandEvent& WXUNUSED(event) )
484 {
485     p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE, 0, 0 );
486
487 #if 0
488     Rebuild();
489 #endif
490 }
491
492 void Playlist::OnSort( wxCommandEvent& WXUNUSED(event) )
493 {
494     playlist_t *p_playlist =
495         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
496                                        FIND_ANYWHERE );
497     if( p_playlist == NULL )
498     {
499         return;
500     }
501
502     playlist_Sort( p_playlist , 0  );
503
504     vlc_object_release( p_playlist );
505
506     Rebuild();
507
508     return;
509 }
510
511 void Playlist::OnRSort( wxCommandEvent& WXUNUSED(event) )
512 {
513     playlist_t *p_playlist =
514         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
515                                        FIND_ANYWHERE );
516     if( p_playlist == NULL )
517     {
518         return;
519     }
520
521     playlist_Sort( p_playlist , 1 );
522
523     vlc_object_release( p_playlist );
524
525     Rebuild();
526
527     return;
528 }
529
530 void Playlist::OnSearchTextChange( wxCommandEvent& WXUNUSED(event) )
531 {
532    search_button->SetDefault();
533 }
534
535 void Playlist::OnSearch( wxCommandEvent& WXUNUSED(event) )
536 {
537     wxString search_string= search_text->GetValue();
538
539     int i_current;
540     int i_first = 0 ;
541     int i_item = -1;
542
543     for( i_current = 0 ; i_current <= listview->GetItemCount() ; i_current++ ) 
544     {
545         if( listview->GetItemState( i_current, wxLIST_STATE_SELECTED)
546                    == wxLIST_STATE_SELECTED )
547         {
548             i_first = i_current;
549             break;
550         }
551     }
552
553     for ( i_current = i_first + 1; i_current <= listview->GetItemCount() ; 
554           i_current++ )
555     {
556         wxListItem listitem;
557         listitem.SetId( i_current );
558         listview->GetItem( listitem );
559         if( listitem.m_text.Lower().Contains( search_string.Lower() ) )
560         {
561             i_item = i_current;
562             break;
563         }
564     }
565     for( long item = 0; item < listview->GetItemCount(); item++ )
566     {
567         listview->Select( item, FALSE );
568     }
569  
570     wxListItem listitem;
571     listitem.SetId(i_item);
572     listitem.m_state = wxLIST_STATE_SELECTED;
573     listview->Select( i_item, TRUE );
574     listview->Focus( i_item );
575
576 }
577
578 void Playlist::OnInvertSelection( wxCommandEvent& WXUNUSED(event) )
579 {
580     for( long item = 0; item < listview->GetItemCount(); item++ )
581     {
582         listview->Select( item, ! listview->IsSelected( item ) );
583     }
584 }
585
586 void Playlist::OnDeleteSelection( wxCommandEvent& WXUNUSED(event) )
587 {
588     /* Delete from the end to the beginning, to avoid a shift of indices */
589     for( long item = listview->GetItemCount() - 1; item >= 0; item-- )
590     {
591         if( listview->IsSelected( item ) )
592         {
593             DeleteItem( item );
594         }
595     }
596
597     Rebuild();
598 }
599
600 void Playlist::OnEnableSelection( wxCommandEvent& WXUNUSED(event) )
601 {
602     playlist_t *p_playlist =
603         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
604                                        FIND_ANYWHERE );
605     if( p_playlist == NULL )
606     {
607         return;
608     }
609
610     for( long item = listview->GetItemCount() - 1; item >= 0; item-- )
611     {
612         if( listview->IsSelected( item ) )
613         {
614             playlist_Enable( p_playlist, item );
615         }
616     }
617     vlc_object_release( p_playlist);
618     Rebuild();
619 }
620
621 void Playlist::OnDisableSelection( wxCommandEvent& WXUNUSED(event) )
622 {
623     playlist_t *p_playlist =
624         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
625                                        FIND_ANYWHERE );
626     if( p_playlist == NULL )
627     {
628         return;
629     }
630
631     for( long item = listview->GetItemCount() - 1; item >= 0; item-- )
632     {
633         if( listview->IsSelected( item ) )
634         {
635             playlist_Disable( p_playlist, item );
636         }
637     }
638     vlc_object_release( p_playlist);
639     Rebuild();
640 }
641
642 void Playlist::OnRandom( wxCommandEvent& event )
643 {
644     vlc_value_t val;
645     val.b_bool = event.IsChecked();
646     playlist_t *p_playlist =
647         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
648                                        FIND_ANYWHERE );
649     if( p_playlist == NULL )
650     {
651         return;
652     }
653     var_Set( p_playlist , "random", val);
654     vlc_object_release( p_playlist );
655 }
656 void Playlist::OnLoop ( wxCommandEvent& event )
657 {
658     vlc_value_t val;
659     val.b_bool = event.IsChecked();
660     playlist_t *p_playlist =
661         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
662                                        FIND_ANYWHERE );
663     if( p_playlist == NULL )
664     {
665         return;
666     }
667     var_Set( p_playlist , "loop", val);
668     vlc_object_release( p_playlist );
669 }
670
671 void Playlist::OnRepeat ( wxCommandEvent& event )
672 {
673     vlc_value_t val;
674     val.b_bool = event.IsChecked();
675     playlist_t *p_playlist =
676         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
677                                        FIND_ANYWHERE );
678     if( p_playlist == NULL )
679     {
680         return;
681     }
682     var_Set( p_playlist , "repeat", val);
683     vlc_object_release( p_playlist );
684 }
685
686 void Playlist::OnSelectAll( wxCommandEvent& WXUNUSED(event) )
687 {
688     for( long item = 0; item < listview->GetItemCount(); item++ )
689     {
690         listview->Select( item, TRUE );
691     }
692 }
693
694 void Playlist::OnActivateItem( wxListEvent& event )
695 {
696     playlist_t *p_playlist =
697         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
698                                        FIND_ANYWHERE );
699     if( p_playlist == NULL )
700     {
701         return;
702     }
703     playlist_Goto( p_playlist, event.GetIndex() );
704
705     vlc_object_release( p_playlist );
706 }
707 void Playlist::OnKeyDown( wxListEvent& event )
708 {
709     long keycode = event.GetKeyCode();
710     /* Delete selected items */
711     if( keycode == WXK_BACK || keycode == WXK_DELETE )
712     {
713         /* We send a dummy event */
714         OnDeleteSelection( event );
715     }
716 }
717
718 void Playlist::OnInfos( wxCommandEvent& WXUNUSED(event) )
719 {
720     playlist_t *p_playlist =
721         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
722                                        FIND_ANYWHERE );
723     if( p_playlist == NULL )
724     {
725         return;
726     }
727
728     if( iteminfo_dialog == NULL )
729     {
730         /* We use the first selected item, so find it */
731         long i_item = -1;
732         i_item = listview->GetNextItem(i_item,
733                          wxLIST_NEXT_ALL,
734                          wxLIST_STATE_SELECTED);
735         if( i_item >= 0 && i_item < p_playlist->i_size )
736         {
737             iteminfo_dialog = new ItemInfoDialog(
738                               p_intf, p_playlist->pp_items[i_item], this );
739             if( iteminfo_dialog->ShowModal()  == wxID_OK )
740                 Rebuild();
741             delete iteminfo_dialog;
742             iteminfo_dialog = NULL;
743         }
744     }
745     vlc_object_release( p_playlist );
746 }
747
748
749 void Playlist::OnEnDis( wxCommandEvent& WXUNUSED(event) )
750 {
751     playlist_t *p_playlist =
752         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
753                                        FIND_ANYWHERE );
754     if( p_playlist == NULL )
755     {
756         return;
757     }
758
759     long i_item = -1;
760     i_item = listview->GetNextItem(i_item,
761                        wxLIST_NEXT_ALL,
762                        wxLIST_STATE_SELECTED);
763
764     if( i_item >= 0 && i_item < p_playlist->i_size )
765     {
766        if( p_playlist->pp_items[i_item]->b_enabled == VLC_TRUE)
767            playlist_DisableGroup( p_playlist ,
768                                   p_playlist->pp_items[i_item]->i_group );
769        else
770            playlist_EnableGroup( p_playlist ,
771                                   p_playlist->pp_items[i_item]->i_group );
772        Rebuild();
773     }
774
775     vlc_object_release( p_playlist );
776 }
777 /*****************************************************************************
778  * PlaylistChanged: callback triggered by the intf-change playlist variable
779  *  We don't rebuild the playlist directly here because we don't want the
780  *  caller to block for a too long time.
781  *****************************************************************************/
782 int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
783                      vlc_value_t old_val, vlc_value_t new_val, void *param )
784 {
785     Playlist *p_playlist_dialog = (Playlist *)param;
786     vlc_mutex_lock( &p_playlist_dialog->lock );
787     p_playlist_dialog->b_need_update = VLC_TRUE;
788     vlc_mutex_unlock( &p_playlist_dialog->lock );
789     return VLC_SUCCESS;
790 }