* ./modules/gui/wxwindows/playlist.cpp: added a playlist to the wxwindows interface
[vlc.git] / modules / gui / wxwindows / playlist.cpp
1 /*****************************************************************************
2  * interface.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $$
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 /* Let wxWindows take care of the i18n stuff */
36 #undef _
37
38 #ifdef WIN32                                                 /* mingw32 hack */
39 #undef Yield()
40 #undef CreateDialog()
41 #endif
42
43 #include <wx/wxprec.h>
44 #include <wx/wx.h>
45 #include <wx/listctrl.h>
46
47 #include "wxwindows.h"
48
49 /*****************************************************************************
50  * Event Table.
51  *****************************************************************************/
52
53 /* IDs for the controls and the menu commands */
54 enum
55 {
56     /* menu items */
57     AddUrl_Event = 1,
58     AddDirectory_Event,
59     Close_Event,
60
61     InvertSelection_Event,
62     DeleteSelection_Event,
63     SelectAll_Event,
64
65     /* controls */
66     ListView_Event
67 };
68
69 BEGIN_EVENT_TABLE(Playlist, wxFrame)
70     /* Menu events */
71     EVT_MENU(AddUrl_Event, Playlist::OnAddUrl)
72     EVT_MENU(AddDirectory_Event, Playlist::OnAddDirectory)
73     EVT_MENU(Close_Event, Playlist::OnClose)
74     EVT_MENU(InvertSelection_Event, Playlist::OnInvertSelection)
75     EVT_MENU(DeleteSelection_Event, Playlist::OnDeleteSelection)
76     EVT_MENU(SelectAll_Event, Playlist::OnSelectAll)
77
78     /* Listview events */
79     EVT_LIST_ITEM_ACTIVATED(ListView_Event, Playlist::OnActivateItem)
80     EVT_LIST_KEY_DOWN(ListView_Event, Playlist::OnKeyDown)
81
82     /* Button events */
83     EVT_BUTTON( wxID_OK, Playlist::OnClose)
84
85     /* Special events : we don't want to destroy the window when the user
86      * clicks on (X) */
87     EVT_CLOSE(Playlist::OnClose)
88 END_EVENT_TABLE()
89
90 /*****************************************************************************
91  * Constructor.
92  *****************************************************************************/
93 Playlist::Playlist( intf_thread_t *_p_intf, Interface *_p_main_interface ):
94     wxFrame( _p_main_interface, -1, "Playlist", wxDefaultPosition,
95              wxSize::wxSize( 400, 500 ), wxDEFAULT_FRAME_STYLE )
96 {
97     /* Initializations */
98     p_intf = _p_intf;
99     p_main_interface = _p_main_interface;
100
101     /* Create our "Manage" menu */
102     wxMenu *manage_menu = new wxMenu;
103     manage_menu->Append( AddUrl_Event, _("Add &Url...") );
104     manage_menu->Append( AddDirectory_Event, _("Add &Directory...") );
105     manage_menu->AppendSeparator();
106     manage_menu->Append( Close_Event, _("&Close") );
107
108     /* Create our "Selection" menu */
109     wxMenu *selection_menu = new wxMenu;
110     selection_menu->Append( InvertSelection_Event, _("&Invert") );
111     selection_menu->Append( DeleteSelection_Event, _("&Delete") );
112     selection_menu->Append( SelectAll_Event, _("&Select All") );
113
114     /* Append the freshly created menus to the menu bar */
115     wxMenuBar *menubar = new wxMenuBar( wxMB_DOCKABLE );
116     menubar->Append( manage_menu, _("&Manage") );
117     menubar->Append( selection_menu, _("&Selection") );
118
119     /* Attach the menu bar to the frame */
120     SetMenuBar( menubar );
121
122     /* Create the listview */
123     /* FIXME: the given size is arbitrary, and prevents us from resizing
124      * the window to smaller dimensions. But the sizers don't seem to adjust
125      * themselves to the size of a listview, and with a wxDefaultSize the
126      * playlist window is ridiculously small */
127     listview = new wxListView( this, ListView_Event, wxDefaultPosition,
128                                wxSize( 350, 300 ), wxLC_REPORT );
129     listview->InsertColumn( 0, _("Url") );
130     listview->InsertColumn( 1, _("Duration") );
131     listview->SetColumnWidth( 0, 250 );
132     listview->SetColumnWidth( 1, 100 );
133
134     /* Create the OK button */
135     ok_button = new wxButton( this, wxID_OK, _("OK") );
136     ok_button->SetDefault();
137
138     /* Place everything in sizers */
139     wxBoxSizer *ok_button_sizer = new wxBoxSizer( wxHORIZONTAL );
140     ok_button_sizer->Add( ok_button, 0, wxALL, 5 );
141     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
142     main_sizer->Add( listview, 1, wxEXPAND | wxALL, 5 );
143     main_sizer->Add( ok_button_sizer, 0, wxALIGN_CENTRE );
144
145     SetSizerAndFit( main_sizer );
146 }
147
148 Playlist::~Playlist()
149 {
150 }
151
152 void Playlist::Rebuild()
153 {
154     playlist_t *p_playlist =
155         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
156                                        FIND_ANYWHERE );
157     if( p_playlist == NULL )
158     {
159         return;
160     }
161
162     /* Clear the list... */
163     listview->DeleteAllItems();
164
165     /* ...and rebuild it */
166     vlc_mutex_lock( &p_playlist->object_lock );
167     for( int i = 0; i < p_playlist->i_size; i++ )
168     {
169         wxString filename = p_playlist->pp_items[i]->psz_name;
170         listview->InsertItem( i, filename );
171         /* FIXME: we should try to find the actual duration... */
172         listview->SetItem( i, 1, _("no info") );
173     }
174     vlc_mutex_unlock( &p_playlist->object_lock );
175
176     /* Change the colour for the currenty played stream */
177     wxListItem listitem;
178     listitem.m_itemId = p_playlist->i_index;
179     listitem.SetTextColour( *wxRED );
180     listview->SetItem( listitem );
181
182     vlc_object_release( p_playlist );
183 }
184
185 /* Update the colour of items */
186 void Playlist::Manage()
187 {
188     playlist_t *p_playlist =
189         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
190                                        FIND_ANYWHERE );
191     if( p_playlist == NULL )
192     {
193         return;
194     }
195
196     vlc_mutex_lock( &p_playlist->object_lock );
197     if( p_intf->p_sys->i_playing != p_playlist->i_index )
198     {
199         wxListItem listitem;
200         listitem.m_itemId = p_playlist->i_index;
201         listitem.SetTextColour( *wxRED );
202         listview->SetItem( listitem );
203
204         if( p_intf->p_sys->i_playing != -1 )
205         {
206             listitem.m_itemId = p_intf->p_sys->i_playing;
207             listitem.SetTextColour( *wxBLACK );
208             listview->SetItem( listitem );
209         }
210         p_intf->p_sys->i_playing = p_playlist->i_index;
211     }
212     vlc_mutex_unlock( &p_playlist->object_lock );
213
214     vlc_object_release( p_playlist );
215 }
216
217 /*****************************************************************************
218  * Private methods.
219  *****************************************************************************/
220 void Playlist::DeleteItem( int item )
221 {
222     playlist_t *p_playlist =
223         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
224                                        FIND_ANYWHERE );
225     if( p_playlist == NULL )
226     {
227         return;
228     }
229
230     playlist_Delete( p_playlist, item );
231     listview->DeleteItem( item );
232
233     vlc_object_release( p_playlist );
234 }
235
236 void Playlist::OnClose( wxCommandEvent& WXUNUSED(event) )
237 {
238     Hide();
239 }
240
241 void Playlist::OnAddUrl( wxCommandEvent& WXUNUSED(event) )
242 {
243     /* TODO */
244 }
245
246 void Playlist::OnAddDirectory( wxCommandEvent& WXUNUSED(event) )
247 {
248     /* TODO */
249 }
250
251 void Playlist::OnInvertSelection( wxCommandEvent& WXUNUSED(event) )
252 {
253     for( long item = 0; item < listview->GetItemCount(); item++ )
254     {
255         listview->Select( item, ! listview->IsSelected( item ) );
256     }
257 }
258
259 void Playlist::OnDeleteSelection( wxCommandEvent& WXUNUSED(event) )
260 {
261     /* Delete from the end to the beginning, to avoid a shift of indices */
262     for( long item = listview->GetItemCount() - 1; item >= 0; item-- )
263     {
264         if( listview->IsSelected( item ) )
265         {
266             DeleteItem( item );
267         }
268     }
269
270     Rebuild();
271 }
272
273 void Playlist::OnSelectAll( wxCommandEvent& WXUNUSED(event) )
274 {
275     for( long item = 0; item < listview->GetItemCount(); item++ )
276     {
277         listview->Select( item, TRUE );
278     }
279 }
280
281 void Playlist::OnActivateItem( wxListEvent& event )
282 {
283     playlist_t *p_playlist =
284         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
285                                        FIND_ANYWHERE );
286     if( p_playlist == NULL )
287     {
288         return;
289     }
290
291     playlist_Goto( p_playlist, event.GetIndex() );
292
293     vlc_object_release( p_playlist );
294 }
295
296 void Playlist::OnKeyDown( wxListEvent& event )
297 {
298     long keycode = event.GetKeyCode();
299     /* Delete selected items */
300     if( keycode == WXK_BACK || keycode == WXK_DELETE )
301     {
302         /* We send a dummy event */
303         OnDeleteSelection( event );
304     }
305 }
306