]> git.sesse.net Git - vlc/blob - modules/gui/win32/playlist.cpp
- * : start playing only when opening a stream from the main window;
[vlc] / modules / gui / win32 / playlist.cpp
1 /*****************************************************************************\r
2  * playlist.cpp: Interface for the playlist dialog\r
3  *****************************************************************************\r
4  * Copyright (C) 2002 VideoLAN\r
5  *\r
6  * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  * \r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program; if not, write to the Free Software\r
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
21  *****************************************************************************/\r
22 \r
23 #include <vcl.h>\r
24 #pragma hdrstop\r
25 \r
26 #include <vlc/vlc.h>\r
27 #include <vlc/intf.h>\r
28 \r
29 #include "playlist.h"\r
30 #include "dragdrop.h"\r
31 #include "misc.h"\r
32 #include "win32_common.h"\r
33 \r
34 //---------------------------------------------------------------------------\r
35 #pragma resource "*.dfm"\r
36 \r
37 //---------------------------------------------------------------------------\r
38 _fastcall TPlaylistDlg::TPlaylistDlg(\r
39     TComponent* Owner, intf_thread_t *_p_intf ) : TForm( Owner )\r
40 {\r
41     p_intf = _p_intf;\r
42     Icon = p_intf->p_sys->p_window->Icon;\r
43     Translate( this );\r
44 \r
45     /* store a pointer to the core playlist */\r
46     p_playlist = (playlist_t *)\r
47         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );\r
48     if( p_playlist == NULL )\r
49     {\r
50         msg_Err( p_intf, "cannot find a playlist object" );\r
51     }\r
52 \r
53     /* drag and drop stuff */\r
54 \r
55     /* initialize the OLE library */\r
56     OleInitialize( NULL );\r
57     /* TDropTarget will send the WM_OLEDROP message to the form */\r
58     lpDropTarget = (LPDROPTARGET)new TDropTarget( this->Handle );\r
59     CoLockObjectExternal( lpDropTarget, true, true );\r
60     /* register the listview as a drop target */\r
61     RegisterDragDrop( ListViewPlaylist->Handle, lpDropTarget );\r
62 }\r
63 //---------------------------------------------------------------------------\r
64 __fastcall TPlaylistDlg::~TPlaylistDlg()\r
65 {\r
66     /* release the core playlist */\r
67     vlc_object_release( p_playlist );\r
68 \r
69     /* remove the listview from the list of drop targets */\r
70     RevokeDragDrop( ListViewPlaylist->Handle );\r
71     lpDropTarget->Release();\r
72     CoLockObjectExternal( lpDropTarget, false, true );\r
73     /* uninitialize the OLE library */\r
74     OleUninitialize();\r
75 }\r
76 //---------------------------------------------------------------------------\r
77 char * __fastcall TPlaylistDlg::rindex( char *s, char c )\r
78 {\r
79     char *ref = s;\r
80 \r
81     s = s + strlen( s ) - 2;\r
82     while( ( s > ref ) && ( *s != c ) )\r
83     {\r
84         s--;\r
85     }\r
86     if( *s == c )\r
87     {\r
88         return( s );\r
89     }\r
90     else\r
91     {\r
92         return( NULL );\r
93     }\r
94 }\r
95 //---------------------------------------------------------------------------\r
96 \r
97 \r
98 /*****************************************************************************\r
99  * External drop handling\r
100  *****************************************************************************/\r
101 void __fastcall TPlaylistDlg::OnDrop( TMessage &Msg )\r
102 {\r
103     p_intf->p_sys->p_window->OnDrop( Msg );\r
104 }\r
105 //--------------------------------------------------------------------------\r
106 \r
107 \r
108 /*****************************************************************************\r
109  * Event handlers\r
110  ****************************************************************************/\r
111 void __fastcall TPlaylistDlg::FormShow( TObject *Sender )\r
112 {\r
113     p_intf->p_sys->p_window->PlaylistAction->Checked = true;\r
114 }\r
115 //---------------------------------------------------------------------------\r
116 void __fastcall TPlaylistDlg::FormHide( TObject *Sender )\r
117 {\r
118     p_intf->p_sys->p_window->PlaylistAction->Checked = false;\r
119 }\r
120 //---------------------------------------------------------------------------\r
121 void __fastcall TPlaylistDlg::BitBtnOkClick( TObject *Sender )\r
122 {\r
123     Hide();\r
124 }\r
125 //---------------------------------------------------------------------------\r
126 void __fastcall TPlaylistDlg::PlayStreamActionExecute( TObject *Sender )\r
127 {\r
128     TListItem *Item;\r
129     TListItem *ItemStart;\r
130     TItemStates Focused;\r
131 \r
132     if( p_playlist == NULL )\r
133         return;\r
134 \r
135     /* search the selected item */\r
136     if( ListViewPlaylist->SelCount > 0 )\r
137     {\r
138         if( ListViewPlaylist->SelCount == 1 )\r
139         {\r
140             Item = ListViewPlaylist->Selected;\r
141         }\r
142         else\r
143         {\r
144             Focused << isFocused;\r
145             ItemStart = ListViewPlaylist->Items->Item[0];\r
146 \r
147             Item = ListViewPlaylist->GetNextItem( ItemStart, sdAll, Focused );\r
148         }\r
149 \r
150         playlist_Goto( p_playlist, Item->Index );\r
151     }\r
152 }\r
153 //---------------------------------------------------------------------------\r
154 void __fastcall TPlaylistDlg::ListViewPlaylistKeyDown( TObject *Sender,\r
155         WORD &Key, TShiftState Shift )\r
156 {\r
157     /* 'suppr' or 'backspace' */\r
158     if( ( Key == VK_DELETE ) || ( Key == VK_BACK ) )\r
159     {\r
160         DeleteSelectionActionExecute( Sender );\r
161     }\r
162 \r
163     /* 'enter' */\r
164     if( Key == VK_RETURN )\r
165     {\r
166         PlayStreamActionExecute( Sender );\r
167     }\r
168 }\r
169 //---------------------------------------------------------------------------\r
170 void __fastcall TPlaylistDlg::ListViewPlaylistCustomDrawItem(\r
171         TCustomListView *Sender, TListItem *Item, TCustomDrawState State,\r
172         bool &DefaultDraw)\r
173 {\r
174     TRect Rect = Item->DisplayRect( drBounds );\r
175 \r
176     /* set the background color */\r
177     if( Item->Index == p_intf->p_sys->i_playing )\r
178         Sender->Canvas->Brush->Color = clRed;\r
179     else\r
180         Sender->Canvas->Brush->Color = clWhite;\r
181 \r
182     Sender->Canvas->FillRect( Rect );\r
183 }\r
184 //---------------------------------------------------------------------------\r
185 \r
186 \r
187 /*****************************************************************************\r
188  * Menu and popup callbacks\r
189  ****************************************************************************/\r
190 void __fastcall TPlaylistDlg::MenuAddFileClick( TObject *Sender )\r
191 {\r
192     p_intf->p_sys->b_play_when_adding = false;\r
193     p_intf->p_sys->p_window->OpenFileActionExecute( Sender );\r
194     p_intf->p_sys->b_play_when_adding = true;\r
195 }\r
196 //---------------------------------------------------------------------------\r
197 void __fastcall TPlaylistDlg::MenuAddDiscClick( TObject *Sender )\r
198 {\r
199     p_intf->p_sys->b_play_when_adding = false;\r
200     p_intf->p_sys->p_window->OpenDiscActionExecute( Sender );\r
201     p_intf->p_sys->b_play_when_adding = true;\r
202 }\r
203 //---------------------------------------------------------------------------\r
204 void __fastcall TPlaylistDlg::MenuAddNetClick( TObject *Sender )\r
205 {\r
206     p_intf->p_sys->b_play_when_adding = false;\r
207     p_intf->p_sys->p_window->NetworkStreamActionExecute( Sender );\r
208     p_intf->p_sys->b_play_when_adding = true;\r
209 }\r
210 //---------------------------------------------------------------------------\r
211 void __fastcall TPlaylistDlg::MenuAddUrlClick( TObject *Sender )\r
212 {\r
213     /* TODO */\r
214 }\r
215 //---------------------------------------------------------------------------\r
216 void __fastcall TPlaylistDlg::DeleteSelectionActionExecute( TObject *Sender )\r
217 {\r
218     /* user wants to delete a file in the queue */\r
219     int i_pos;\r
220 \r
221     /* lock the struct */\r
222     vlc_mutex_lock( &p_intf->change_lock );\r
223 \r
224     /* delete the items from the last to the first */\r
225     for( i_pos = p_playlist->i_size - 1; i_pos >= 0; i_pos-- )\r
226     {\r
227         if( ListViewPlaylist->Items->Item[i_pos]->Selected )\r
228         {\r
229             DeleteItem( i_pos );\r
230         }\r
231     }\r
232 \r
233     /* rebuild the ListView */\r
234     UpdateGrid();\r
235 \r
236     vlc_mutex_unlock( &p_intf->change_lock );\r
237 }\r
238 //---------------------------------------------------------------------------\r
239 void __fastcall TPlaylistDlg::DeleteAllActionExecute( TObject *Sender )\r
240 {\r
241     int i_pos;\r
242 \r
243     /* lock the struct */\r
244     vlc_mutex_lock( &p_intf->change_lock );\r
245 \r
246     /* delete the items from the last to the first */\r
247     for( i_pos = p_playlist->i_size - 1; i_pos >= 0; i_pos-- )\r
248     {\r
249         DeleteItem( i_pos );\r
250     }\r
251 \r
252     /* Rebuild the ListView */\r
253     UpdateGrid();\r
254 \r
255     vlc_mutex_unlock( &p_intf->change_lock );\r
256 }\r
257 //---------------------------------------------------------------------------\r
258 void __fastcall TPlaylistDlg::InvertSelectionActionExecute( TObject *Sender )\r
259 {\r
260 #define NOT( var ) ( (var) ? false : true )\r
261     int         i_pos;\r
262     TListItems *Items = ListViewPlaylist->Items;\r
263 \r
264     /* delete the items from the last to the first */\r
265     for( i_pos = p_playlist->i_size - 1; i_pos >= 0; i_pos-- )\r
266     {\r
267         Items->Item[i_pos]->Selected = NOT( Items->Item[i_pos]->Selected );\r
268     }\r
269 #undef NOT\r
270 }\r
271 //---------------------------------------------------------------------------\r
272 void __fastcall TPlaylistDlg::CropSelectionActionExecute( TObject *Sender )\r
273 {\r
274     InvertSelectionActionExecute( Sender );\r
275     DeleteSelectionActionExecute( Sender );\r
276 }\r
277 //---------------------------------------------------------------------------\r
278 \r
279 \r
280 /*****************************************************************************\r
281  * Useful functions, needed by the event handlers or by other windows\r
282  ****************************************************************************/\r
283 void __fastcall TPlaylistDlg::Add( AnsiString FileName, int i_mode, int i_pos )\r
284 {\r
285     if( p_playlist == NULL )\r
286         return;\r
287 \r
288     playlist_Add( p_playlist, FileName.c_str(), i_mode, i_pos );\r
289     \r
290     /* refresh the display */\r
291     UpdateGrid();\r
292 }\r
293 //---------------------------------------------------------------------------\r
294 void __fastcall TPlaylistDlg::Stop()\r
295 {\r
296     if( p_playlist == NULL )\r
297         return;\r
298 \r
299     playlist_Stop( p_playlist );\r
300 }\r
301 //---------------------------------------------------------------------------\r
302 void __fastcall TPlaylistDlg::Play()\r
303 {\r
304     if( p_playlist == NULL )\r
305         return;\r
306 \r
307     if ( p_playlist->i_size )\r
308         playlist_Play( p_playlist );\r
309     else\r
310         Show();\r
311 }\r
312 //---------------------------------------------------------------------------\r
313 void __fastcall TPlaylistDlg::Pause()\r
314 {\r
315     if( p_intf->p_sys->p_input != NULL )\r
316     {\r
317         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );\r
318     }\r
319 }\r
320 //---------------------------------------------------------------------------\r
321 void __fastcall TPlaylistDlg::Slow()\r
322 {\r
323     if( p_intf->p_sys->p_input != NULL )\r
324     {\r
325         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );\r
326     }\r
327 }\r
328 //---------------------------------------------------------------------------\r
329 void __fastcall TPlaylistDlg::Fast()\r
330 {\r
331     if( p_intf->p_sys->p_input != NULL )\r
332     {\r
333         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );\r
334     }\r
335 }\r
336 //---------------------------------------------------------------------------\r
337 void __fastcall TPlaylistDlg::UpdateGrid()\r
338 {\r
339     int i_dummy;\r
340     char *FileName;\r
341     TListItem *Item;\r
342 \r
343     ListViewPlaylist->Items->BeginUpdate();\r
344 \r
345     /* Clear the list... */\r
346     ListViewPlaylist->Items->Clear();\r
347 \r
348     /* ...and rebuild it */\r
349     for( i_dummy = 0; i_dummy < p_playlist->i_size; i_dummy++ )\r
350     {\r
351 #ifdef WIN32\r
352         /* Position of the last '\' in the string */\r
353         FileName = rindex( p_playlist->pp_items[i_dummy]->psz_name, '\\' );\r
354 #else\r
355         /* Position of the last '/' in the string */\r
356         FileName = rindex( p_playlist->pp_items[i_dummy]->psz_name, '/' );\r
357 #endif\r
358         if( ( FileName == NULL ) || ( *(FileName + 1) == '\0' ) )\r
359         {\r
360             FileName = p_playlist->pp_items[i_dummy]->psz_name;\r
361         }\r
362         else\r
363         {\r
364             /* Skip leading '\' or '/' */\r
365             FileName++;\r
366         }\r
367 \r
368         Item = ListViewPlaylist->Items->Add();\r
369         Item->Caption = FileName;\r
370         Item->SubItems->Add( "no info" );\r
371     }\r
372     /* TODO: Set background color ? */\r
373 \r
374     ListViewPlaylist->Items->EndUpdate();\r
375 }\r
376 //---------------------------------------------------------------------------\r
377 void __fastcall TPlaylistDlg::Manage()\r
378 {\r
379     if( p_playlist == NULL )\r
380         return;\r
381 \r
382     vlc_mutex_lock( &p_playlist->object_lock );\r
383 \r
384     if( p_intf->p_sys->i_playing != p_playlist->i_index )\r
385     {\r
386         p_intf->p_sys->i_playing = p_playlist->i_index;\r
387 \r
388         /* update the background color */\r
389         UpdateGrid();\r
390     }\r
391 \r
392     vlc_mutex_unlock( &p_playlist->object_lock );\r
393 }\r
394 //---------------------------------------------------------------------------\r
395 void __fastcall TPlaylistDlg::DeleteItem( int i_pos )\r
396 {\r
397     if( p_playlist == NULL )\r
398         return;\r
399 \r
400     playlist_Delete( p_playlist, i_pos );\r
401 }\r
402 //---------------------------------------------------------------------------\r
403 void __fastcall TPlaylistDlg::Previous()\r
404 {\r
405     if( p_playlist == NULL )\r
406         return;\r
407 \r
408     playlist_Prev( p_playlist );\r
409 }\r
410 //---------------------------------------------------------------------------\r
411 void __fastcall TPlaylistDlg::Next()\r
412 {\r
413     if( p_playlist == NULL )\r
414         return;\r
415 \r
416     playlist_Next( p_playlist );\r
417 }\r
418 //---------------------------------------------------------------------------\r
419 \r
420 \r
421 void __fastcall TPlaylistDlg::MenuFileCloseClick(TObject *Sender)\r
422 {\r
423     Hide();\r
424 }\r
425 //---------------------------------------------------------------------------\r
426 \r
427 void __fastcall TPlaylistDlg::MenuFileOpenClick(TObject *Sender)\r
428 {\r
429     if ( PlaylistOpenDlg->Execute() )\r
430     {\r
431         playlist_LoadFile ( p_playlist , PlaylistOpenDlg->FileName.c_str() );\r
432         UpdateGrid();\r
433     }\r
434 }\r
435 //---------------------------------------------------------------------------\r
436 \r
437 void __fastcall TPlaylistDlg::MenuFileSaveClick(TObject *Sender)\r
438 {\r
439     if ( PlaylistSaveDlg->Execute() )\r
440     {\r
441         playlist_SaveFile ( p_playlist , PlaylistSaveDlg->FileName.c_str() );\r
442     }\r
443 }\r
444 //---------------------------------------------------------------------------\r
445 \r