]> git.sesse.net Git - vlc/blob - modules/gui/wince/playlist.cpp
* modules/gui/wince: some more code cleanup + fixes.
[vlc] / modules / gui / wince / playlist.cpp
1 /*****************************************************************************
2  * playlist.cpp : WinCE gui plugin for VLC
3  *****************************************************************************
4  * Copyright (C) 2000-2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31 #include <vlc/vlc.h>
32 #include <vlc/intf.h>
33
34 #include "wince.h"
35
36 #include <commctrl.h>
37 #include <commdlg.h>
38
39 #ifndef NMAXFILE
40 #define NMAXFILE 512 // at least 256
41 #endif
42
43 #ifndef TEXTMAXBUF
44 #define TEXTMAXBUF 512 // at least 500
45 #endif
46
47 #define LONG2POINT(l, pt)  ((pt).x = (SHORT)LOWORD(l), (pt).y = (SHORT)HIWORD(l))
48
49 #define NUMIMAGES     11   // Number of buttons in the toolbar           
50 #define IMAGEWIDTH    16   // Width of the buttons in the toolbar  
51 #define IMAGEHEIGHT   16   // Height of the buttons in the toolbar  
52 #define BUTTONWIDTH   0    // Width of the button images in the toolbar
53 #define BUTTONHEIGHT  0    // Height of the button images in the toolbar
54 #define ID_TOOLBAR    2000 // Identifier of the main tool bar
55 #define dwTBFontStyle TBSTYLE_BUTTON | TBSTYLE_CHECK | TBSTYLE_GROUP // style for toolbar buttons
56
57 enum      
58 {
59   Infos_Event = 1000,
60   Up_Event,
61   Down_Event,
62   Random_Event,
63   Loop_Event,
64   Repeat_Event,
65   PopupPlay_Event,
66   PopupDel_Event,
67   PopupEna_Event,
68   PopupInfo_Event  
69 };
70
71 // Help strings
72 #define HELP_OPENPL _T("Open playlist")
73 #define HELP_SAVEPL _T("Save playlist")
74 #define HELP_SIMPLEADD _T("Simple Add")
75 #define HELP_ADDMRL _T("Add MRL")
76 #define HELP_DELETE _T("Delete selection")
77 #define HELP_INFOS _T("Item info")
78 #define HELP_UP _T("Up")
79 #define HELP_DOWN _T("Down")
80 #define HELP_RANDOM _T("Random")
81 #define HELP_LOOP _T("Repeat all")
82 #define HELP_REPEAT _T("Repeat one")
83
84 // The TBBUTTON structure contains information the toolbar buttons.
85 static TBBUTTON tbButton2[] =      
86 {
87   {0, ID_MANAGE_OPENPL,        TBSTATE_ENABLED, TBSTYLE_BUTTON},
88   {1, ID_MANAGE_SAVEPL,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
89   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
90   {2, ID_MANAGE_SIMPLEADD,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
91   {3, ID_MANAGE_ADDMRL,        TBSTATE_ENABLED, TBSTYLE_BUTTON},
92   {4, ID_SEL_DELETE,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
93   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
94   {5, Infos_Event,      TBSTATE_ENABLED, TBSTYLE_BUTTON},
95   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
96   {6, Up_Event,      TBSTATE_ENABLED, TBSTYLE_BUTTON},
97   {7, Down_Event,      TBSTATE_ENABLED, TBSTYLE_BUTTON},
98   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
99   {8, Random_Event,      TBSTATE_ENABLED, TBSTYLE_CHECK},
100   {9, Loop_Event,       TBSTATE_ENABLED, TBSTYLE_CHECK},
101   {10, Repeat_Event,       TBSTATE_ENABLED, TBSTYLE_CHECK}
102 };
103
104 // Toolbar ToolTips
105 TCHAR * szToolTips2[] = 
106 {
107     HELP_OPENPL,
108     HELP_SAVEPL,
109     HELP_SIMPLEADD,
110     HELP_ADDMRL,
111     HELP_DELETE,
112     HELP_INFOS,
113     HELP_UP,
114     HELP_DOWN,
115     HELP_RANDOM,
116     HELP_LOOP,
117     HELP_REPEAT
118 };
119
120 /*****************************************************************************
121  * Event Table.
122  *****************************************************************************/
123
124 /*****************************************************************************
125  * Constructor.
126  *****************************************************************************/
127 Playlist::Playlist( intf_thread_t *_p_intf, HINSTANCE _hInst )
128 {
129     /* Initializations */
130     p_intf = _p_intf;
131         hInst = _hInst;
132         hListView = NULL;
133
134     i_title_sorted = 1;
135     i_author_sorted = 1;
136
137     b_need_update = VLC_TRUE;
138 }
139
140 /***********************************************************************
141 FUNCTION: 
142   WndProc
143
144 PURPOSE: 
145   Processes messages sent to the main window.
146 ***********************************************************************/
147 LRESULT Playlist::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
148 {
149     SHINITDLGINFO shidi;
150     SHMENUBARINFO mbi;
151     INITCOMMONCONTROLSEX iccex;
152     RECT rect, rectTB;
153     DWORD dwStyle;
154
155     int bState;
156     playlist_t *p_playlist;
157
158     switch( msg )
159     {
160     case WM_INITDIALOG: 
161         shidi.dwMask = SHIDIM_FLAGS;
162         shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN |
163             SHIDIF_FULLSCREENNOMENUBAR;//SHIDIF_SIZEDLGFULLSCREEN;
164         shidi.hDlg = hwnd;
165         SHInitDialog( &shidi );
166
167         //Create the menubar.
168         memset( &mbi, 0, sizeof (SHMENUBARINFO) );
169         mbi.cbSize     = sizeof (SHMENUBARINFO);
170         mbi.hwndParent = hwnd;
171         mbi.dwFlags    = SHCMBF_HMENU;
172         mbi.nToolBarId = IDR_MENUBAR2;
173         mbi.hInstRes   = hInst;
174         mbi.nBmpId     = 0;
175         mbi.cBmpImages = 0;  
176
177         if( !SHCreateMenuBar(&mbi) )
178         {
179             MessageBox(hwnd, _T("SHCreateMenuBar Failed"), _T("Error"), MB_OK);
180             //return -1;
181         }
182
183         hwndCB = mbi.hwndMB;
184
185         iccex.dwSize = sizeof (INITCOMMONCONTROLSEX);
186         iccex.dwICC = ICC_BAR_CLASSES;
187
188         // Registers TOOLBAR control classes from the common control dll
189         InitCommonControlsEx (&iccex);
190
191         //  Create the toolbar control.
192         dwStyle = WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS |
193             WS_EX_OVERLAPPEDWINDOW | CCS_NOPARENTALIGN;
194
195         hwndTB = CreateToolbarEx( hwnd, dwStyle, 0, NUMIMAGES,
196                                   hInst, IDB_BITMAP3, tbButton2,
197                                   sizeof (tbButton2) / sizeof (TBBUTTON),
198                                   BUTTONWIDTH, BUTTONHEIGHT,
199                                   IMAGEWIDTH, IMAGEHEIGHT, sizeof(TBBUTTON) );
200         if( !hwndTB ) break;
201   
202         // Add ToolTips to the toolbar.
203         SendMessage( hwndTB, TB_SETTOOLTIPS, (WPARAM) NUMIMAGES,
204                      (LPARAM)szToolTips2 );
205
206         // Reposition the toolbar.
207         GetClientRect( hwnd, &rect );
208         GetWindowRect( hwndTB, &rectTB );
209         MoveWindow( hwndTB, rect.left, rect.top - 2, rect.right - rect.left, 
210                     MENU_HEIGHT /*rectTB.bottom - rectTB.top */, TRUE);
211
212         // random, loop, repeat buttons states
213         vlc_value_t val; 
214         p_playlist = (playlist_t *)
215             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
216         if( !p_playlist ) break;
217
218         var_Get( p_playlist , "random", &val );
219         bState = val.b_bool ? TBSTATE_CHECKED : 0;
220         SendMessage( hwndTB, TB_SETSTATE, Random_Event,
221                      MAKELONG(bState | TBSTATE_ENABLED, 0) );
222         var_Get( p_playlist , "loop", &val );
223         bState = val.b_bool ? TBSTATE_CHECKED : 0;
224         SendMessage( hwndTB, TB_SETSTATE, Loop_Event,
225                      MAKELONG(bState | TBSTATE_ENABLED, 0) );
226         var_Get( p_playlist , "repeat", &val );
227         bState = val.b_bool ? TBSTATE_CHECKED : 0;
228         SendMessage( hwndTB, TB_SETSTATE, Repeat_Event,
229                      MAKELONG(bState | TBSTATE_ENABLED, 0) );
230         vlc_object_release( p_playlist );
231
232         GetClientRect( hwnd, &rect );
233         hListView = CreateWindow( WC_LISTVIEW, NULL, WS_VISIBLE | WS_CHILD |
234             LVS_REPORT | LVS_SHOWSELALWAYS | WS_VSCROLL | WS_HSCROLL,
235             rect.left, rect.top + 2*(MENU_HEIGHT+1), rect.right - rect.left, 
236             rect.bottom - ( rect.top + 2*MENU_HEIGHT) - MENU_HEIGHT, 
237             hwnd, NULL, hInst, NULL );
238         ListView_SetExtendedListViewStyle( hListView, LVS_EX_FULLROWSELECT );
239
240         LVCOLUMN lv;
241         lv.mask = LVCF_WIDTH | LVCF_FMT | LVCF_TEXT;
242         lv.fmt = LVCFMT_LEFT ;
243         GetClientRect( hwnd, &rect );
244         lv.cx = 120;
245         lv.pszText = _T("Name");
246         lv.cchTextMax = 9;
247         ListView_InsertColumn( hListView, 0, &lv);
248         lv.cx = 55;
249         lv.pszText = _T("Author");
250         lv.cchTextMax = 9;
251         ListView_InsertColumn( hListView, 1, &lv);
252         lv.cx = rect.right - rect.left - 180;
253         lv.pszText = _T("Duration");
254         lv.cchTextMax = 9;
255         ListView_InsertColumn( hListView, 2, &lv);
256
257         SetTimer( hwnd, 1, 500 /*milliseconds*/, NULL );
258
259         SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
260         break;
261
262     case WM_TIMER:
263         UpdatePlaylist();
264         break;
265
266     case WM_CLOSE:
267         EndDialog( hwnd, LOWORD( wp ) );
268         break;
269
270     case WM_COMMAND:    
271         switch( LOWORD(wp) )
272         {
273         case IDOK:
274             EndDialog( hwnd, LOWORD( wp ) );
275             break;
276
277         case ID_MANAGE_OPENPL:
278             OnOpen();
279             b_need_update = VLC_TRUE;
280             break;
281
282         case ID_MANAGE_SAVEPL:
283             SHFullScreen( GetForegroundWindow(), SHFS_SHOWSIPBUTTON );
284             OnSave();
285             SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
286             break;
287
288         case ID_MANAGE_SIMPLEADD:
289             SHFullScreen( GetForegroundWindow(), SHFS_SHOWSIPBUTTON );
290             OnAddFile();
291             SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
292             b_need_update = VLC_TRUE;
293             break;
294
295         case ID_MANAGE_ADDMRL:
296             SHFullScreen( GetForegroundWindow(), SHFS_SHOWSIPBUTTON );
297             OnAddMRL();
298             SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
299             b_need_update = VLC_TRUE;
300             break;
301
302         case ID_SEL_DELETE:
303             OnDeleteSelection();
304             b_need_update = VLC_TRUE;
305             break;
306
307         case Infos_Event:
308             SHFullScreen( GetForegroundWindow(), SHFS_SHOWSIPBUTTON );
309             OnPopupInfo( hwnd );
310             SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
311             b_need_update = VLC_TRUE;
312             break;
313
314         case Up_Event:
315             OnUp();
316             b_need_update = VLC_TRUE;
317             break;
318
319         case Down_Event:
320             OnDown();
321             b_need_update = VLC_TRUE;
322             break;
323
324         case Random_Event:
325             OnRandom();
326             break;
327
328         case Loop_Event:
329             OnLoop();
330             break;
331
332         case Repeat_Event:
333             OnRepeat();
334             break;
335
336         case ID_SORT_TITLE:
337             OnSort( ID_SORT_TITLE );
338             break;
339
340         case ID_SORT_RTITLE:
341             OnSort( ID_SORT_RTITLE );
342             break;
343
344         case ID_SORT_AUTHOR:
345             OnSort( ID_SORT_AUTHOR );
346             break;
347
348         case ID_SORT_RAUTHOR:
349             OnSort( ID_SORT_RAUTHOR );
350             break;
351
352         case ID_SORT_SHUFFLE:
353             OnSort( ID_SORT_SHUFFLE );
354             break;
355
356         case ID_SEL_ENABLE:
357             OnEnableSelection();
358             break;
359
360         case ID_SEL_DISABLE:
361             OnDisableSelection();
362             break;
363
364         case ID_SEL_INVERT:
365             OnInvertSelection();
366             break;
367
368         case ID_SEL_SELECTALL:
369             OnSelectAll();
370             break;
371
372         case PopupPlay_Event:
373             OnPopupPlay();
374             b_need_update = VLC_TRUE;
375             break;
376
377         case PopupDel_Event:
378             OnPopupDel();
379             b_need_update = VLC_TRUE;
380             break;
381
382         case PopupEna_Event:
383             OnPopupEna();
384             b_need_update = VLC_TRUE;
385             break;
386
387         case PopupInfo_Event:
388             OnPopupInfo( hwnd );
389             SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
390             b_need_update = VLC_TRUE;
391             break;
392
393         default:
394             break;
395         }
396
397     case WM_NOTIFY:
398         if( ( ((LPNMHDR)lp)->hwndFrom == hListView ) &&
399             ( ((LPNMHDR)lp)->code == NM_CUSTOMDRAW ) )
400         {
401             SetWindowLong( hwnd, DWL_MSGRESULT,
402                            (LONG)ProcessCustomDraw(lp) );
403         }
404         else if( ( ((LPNMHDR)lp)->hwndFrom == hListView ) &&
405                  ( ((LPNMHDR)lp)->code == GN_CONTEXTMENU  ) )
406         {                       
407             HandlePopupMenu( hwnd, ((PNMRGINFO)lp)->ptAction );
408         }
409         else if( ( ((LPNMHDR)lp)->hwndFrom == hListView ) &&
410                  ( ((LPNMHDR)lp)->code == LVN_COLUMNCLICK  ) )
411         {
412             OnColSelect( ((LPNMLISTVIEW)lp)->iSubItem );
413         }
414         else if( ( ((LPNMHDR)lp)->hwndFrom == hListView ) &&
415                  ( ((LPNMHDR)lp)->code == LVN_ITEMACTIVATE  ) )
416         {
417             OnActivateItem( ((LPNMLISTVIEW)lp)->iSubItem );
418         }
419         break;
420
421     default:
422          // the message was not processed
423          // indicate if the base class handled it
424         break;
425     }
426
427     return FALSE;
428 }
429
430 LRESULT Playlist::ProcessCustomDraw( LPARAM lParam )
431 {
432     LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
433
434     switch( lplvcd->nmcd.dwDrawStage )
435     {
436     case CDDS_PREPAINT : //Before the paint cycle begins
437         //request notifications for individual listview items
438         return CDRF_NOTIFYITEMDRAW;
439
440     case CDDS_ITEMPREPAINT: //Before an item is drawn
441         playlist_t *p_playlist = (playlist_t *)
442             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
443         if( p_playlist == NULL ) return CDRF_DODEFAULT;
444         if( (int)lplvcd->nmcd.dwItemSpec == p_playlist->i_index )
445         {
446             lplvcd->clrText = RGB(255,0,0);
447             vlc_object_release(p_playlist);
448             return CDRF_NEWFONT;
449         }
450         
451         playlist_item_t *p_item = playlist_ItemGetByPos( p_playlist,
452                                         (int)lplvcd->nmcd.dwItemSpec );
453         if( !p_item )
454         {
455             vlc_object_release(p_playlist);
456             return CDRF_DODEFAULT;
457         }
458         if( p_item->b_enabled == VLC_FALSE )
459         {
460             lplvcd->clrText = RGB(192,192,192);
461             vlc_object_release(p_playlist);
462             return CDRF_NEWFONT;
463         }
464     }
465
466     return CDRF_DODEFAULT;
467 }
468
469 /**********************************************************************
470  * Handles the display of the "floating" popup
471  **********************************************************************/
472 void Playlist::HandlePopupMenu( HWND hwnd, POINT point )
473 {
474     HMENU hMenuTrackPopup;
475
476     // Create the popup menu.
477     hMenuTrackPopup = CreatePopupMenu();
478
479     // Append some items.
480     AppendMenu( hMenuTrackPopup, MF_STRING, PopupPlay_Event, _T("Play") );
481     AppendMenu( hMenuTrackPopup, MF_STRING, PopupDel_Event, _T("Delete") );
482     AppendMenu( hMenuTrackPopup, MF_STRING, PopupEna_Event,
483                 _T("Toggle enabled") );
484     AppendMenu( hMenuTrackPopup, MF_STRING, PopupInfo_Event, _T("Info") );
485
486     /* Draw and track the "floating" popup */
487     TrackPopupMenu( hMenuTrackPopup, 0, point.x, point.y, 0, hwnd, NULL );
488
489     /* Destroy the menu since were are done with it. */
490     DestroyMenu( hMenuTrackPopup );
491 }
492
493 /**********************************************************************
494  * Update the playlist
495  **********************************************************************/
496 void Playlist::UpdatePlaylist()
497 {
498     if( b_need_update )
499     {
500         Rebuild();
501         b_need_update = VLC_FALSE;
502     }
503         
504     playlist_t *p_playlist = (playlist_t *)
505         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
506     if( p_playlist == NULL ) return;
507         
508     /* Update the colour of items */
509
510     vlc_mutex_lock( &p_playlist->object_lock );
511     if( p_intf->p_sys->i_playing != p_playlist->i_index )
512     {
513         // p_playlist->i_index in RED
514         Rebuild();
515
516         // if exists, p_intf->p_sys->i_playing in BLACK
517         p_intf->p_sys->i_playing = p_playlist->i_index;
518     }
519     vlc_mutex_unlock( &p_playlist->object_lock );
520
521     vlc_object_release( p_playlist );
522 }
523
524 /**********************************************************************
525  * Rebuild the playlist
526  **********************************************************************/
527 void Playlist::Rebuild()
528 {
529     playlist_t *p_playlist = (playlist_t *)
530         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
531     if( p_playlist == NULL ) return;
532
533     int i_focused =
534         ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
535
536     /* Clear the list... */
537     ListView_DeleteAllItems( hListView );
538
539     /* ...and rebuild it */
540     vlc_mutex_lock( &p_playlist->object_lock );
541     for( int i = 0; i < p_playlist->i_size; i++ )
542     {
543         LVITEM lv;
544         lv.mask = LVIF_TEXT;
545         lv.pszText = _T("");
546         lv.cchTextMax = 1;
547         lv.iSubItem = 0;
548         lv.iItem = i;
549         ListView_InsertItem( hListView, &lv );
550         ListView_SetItemText( hListView, lv.iItem, 0,
551             _FROMMB(p_playlist->pp_items[i]->input.psz_name) );
552         UpdateItem( i );
553     }
554     vlc_mutex_unlock( &p_playlist->object_lock );
555
556     if ( i_focused )
557         ListView_SetItemState( hListView, i_focused, LVIS_FOCUSED |
558                                LVIS_SELECTED, LVIS_STATEIMAGEMASK )
559     else
560         ListView_SetItemState( hListView, i_focused, LVIS_FOCUSED,
561                                LVIS_STATEIMAGEMASK );
562
563     vlc_object_release( p_playlist );
564 }
565
566 /**********************************************************************
567  * Update one playlist item
568  **********************************************************************/
569 void Playlist::UpdateItem( int i )
570 {
571     playlist_t *p_playlist = (playlist_t *)
572         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
573
574     if( p_playlist == NULL ) return;
575
576     playlist_item_t *p_item = playlist_ItemGetByPos( p_playlist, i );
577
578     if( !p_item )
579     {
580         vlc_object_release(p_playlist);
581         return;
582     }
583
584     ListView_SetItemText( hListView, i, 0, _FROMMB(p_item->input.psz_name) );
585     ListView_SetItemText( hListView, i, 1,
586                           _FROMMB( vlc_input_item_GetInfo( &p_item->input,
587                                    _("General") , _("Author") ) ) );
588
589     char psz_duration[MSTRTIME_MAX_SIZE];
590     mtime_t dur = p_item->input.i_duration;
591     if( dur != -1 ) secstotimestr( psz_duration, dur/1000000 );
592     else memcpy( psz_duration , "-:--:--", sizeof("-:--:--") );
593
594     ListView_SetItemText( hListView, i, 3, _FROMMB(psz_duration) );
595
596     vlc_object_release(p_playlist);
597 }
598
599 /**********************************************************************
600  * Private functions
601  **********************************************************************/
602 void Playlist::DeleteItem( int item )
603 {
604     playlist_t *p_playlist = (playlist_t *)
605         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
606     if( p_playlist == NULL ) return;
607
608     playlist_Delete( p_playlist, item );
609     ListView_DeleteItem( hListView, item );
610
611     vlc_object_release( p_playlist );
612 }
613
614 /**********************************************************************
615  * I/O functions
616  **********************************************************************/
617 void Playlist::OnOpen()
618 {
619     OPENFILENAME ofn;
620     TCHAR DateiName[80+1] = _T("\0");
621     static TCHAR szFilter[] = _T("All playlists (*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u)\0*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u\0");
622
623     playlist_t *p_playlist = (playlist_t *)
624         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
625     if( p_playlist == NULL ) return;
626
627     memset( &ofn, 0, sizeof(OPENFILENAME) );
628     ofn.lStructSize = sizeof (OPENFILENAME);
629     ofn.hwndOwner = NULL;
630     ofn.hInstance = hInst;
631     ofn.lpstrFilter = szFilter;
632     ofn.lpstrCustomFilter = NULL;
633     ofn.nMaxCustFilter = 0;
634     ofn.nFilterIndex = 1;     
635     ofn.lpstrFile = (LPTSTR) DateiName; 
636     ofn.nMaxFile = 80;
637     ofn.lpstrFileTitle = NULL; 
638     ofn.nMaxFileTitle = 40;
639     ofn.lpstrInitialDir = NULL;
640     ofn.lpstrTitle = _T("Open playlist");
641     ofn.Flags = 0; 
642     ofn.nFileOffset = 0;
643     ofn.nFileExtension = 0;
644     ofn.lpstrDefExt = NULL;
645     ofn.lCustData = 0L;
646     ofn.lpfnHook = NULL;
647     ofn.lpTemplateName = NULL;
648
649     if( GetOpenFileName((LPOPENFILENAME)&ofn) )
650     {
651         playlist_Import( p_playlist, _TOMB(ofn.lpstrFile) );
652     }
653
654     vlc_object_release( p_playlist );
655 }
656
657 void Playlist::OnSave()
658 {
659     TCHAR szFile[NMAXFILE] = _T("\0");
660     OPENFILENAME ofn;
661     TCHAR psz_filters[1000];
662
663     struct
664     {
665         char *psz_desc;
666         char *psz_filter;
667         char *psz_module;
668
669     } formats[] =
670     { { "M3U file", "*.m3u", "export-m3u" },       
671       { "PLS file", "*.pls", "export-pls" }
672     };
673
674     for( int i_len = 0, i = 0; i < sizeof(formats)/sizeof(formats[0]); i++ )
675     {
676         _tcscpy( psz_filters + i_len, _FROMMB(formats[i].psz_desc) );
677         i_len = i_len + _tcslen( psz_filters + i_len );
678         psz_filters[i_len++] = '\0';
679         _tcscpy( psz_filters + i_len, _FROMMB(formats[i].psz_filter) );
680         i_len = i_len + _tcslen( psz_filters + i_len );
681         psz_filters[i_len++] = '\0';
682         if( i == sizeof(formats)/sizeof(formats[0]) -1 )
683             psz_filters[i_len] = '\0';
684     }
685
686     memset( &(ofn), 0, sizeof(ofn));
687     ofn.lStructSize     = sizeof(ofn);
688     ofn.hwndOwner = NULL;
689     ofn.lpstrFile = szFile;
690     ofn.nMaxFile = NMAXFILE;    
691     ofn.lpstrFilter = psz_filters;
692     ofn.lpstrTitle = _T("Save playlist");
693     ofn.Flags = OFN_HIDEREADONLY; 
694
695     if( GetSaveFileName( (LPOPENFILENAME)&ofn ) )
696     {
697         playlist_t * p_playlist = (playlist_t *)
698             vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
699
700         if( p_playlist && ofn.lpstrFile )
701         {
702             playlist_Export( p_playlist, _TOMB(ofn.lpstrFile),
703                              formats[ofn.nFilterIndex ?
704                                      ofn.nFilterIndex - 1 : 0].psz_module );
705         }
706
707         if( p_playlist ) vlc_object_release( p_playlist );
708     }
709 }
710
711 void Playlist::OnAddFile()
712 {
713     // Same code as in Interface
714     OPENFILENAME ofn;
715     TCHAR DateiName[80+1] = _T("\0");
716     static TCHAR szFilter[] = _T("All (*.*)\0*.*\0");
717
718     playlist_t *p_playlist = (playlist_t *)
719         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
720     if( p_playlist == NULL ) return;
721
722     memset( &ofn, 0, sizeof(OPENFILENAME) );
723     ofn.lStructSize = sizeof(OPENFILENAME);
724     ofn.hwndOwner = NULL;
725     ofn.hInstance = hInst;
726     ofn.lpstrFilter = szFilter;
727     ofn.lpstrCustomFilter = NULL;
728     ofn.nMaxCustFilter = 0;
729     ofn.nFilterIndex = 1;     
730     ofn.lpstrFile = (LPTSTR)DateiName; 
731     ofn.nMaxFile = 80;
732     ofn.lpstrFileTitle = NULL; 
733     ofn.nMaxFileTitle = 40;
734     ofn.lpstrInitialDir = NULL;
735     ofn.lpstrTitle = _T("Quick Open File");
736     ofn.Flags = 0; 
737     ofn.nFileOffset = 0;
738     ofn.nFileExtension = 0;
739     ofn.lpstrDefExt = NULL;
740     ofn.lCustData = 0L;
741     ofn.lpfnHook = NULL;
742     ofn.lpTemplateName = NULL;
743
744     SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
745
746     if( GetOpenFileName( (LPOPENFILENAME)&ofn ) )
747     {
748         char *psz_filename = _TOMB(ofn.lpstrFile);
749         playlist_Add( p_playlist, psz_filename, psz_filename,
750                       PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
751     }
752
753     vlc_object_release( p_playlist );
754 }
755
756 void Playlist::OnAddMRL()
757 {
758 }
759
760 /**********************************************************************
761  * Selection functions
762  **********************************************************************/
763 void Playlist::OnDeleteSelection()
764 {
765     /* Delete from the end to the beginning, to avoid a shift of indices */
766     for( long item = ((int) ListView_GetItemCount( hListView ) - 1);
767          item >= 0; item-- )
768     {
769         if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
770         {
771             DeleteItem( item );
772         }
773     }
774 }
775
776 void Playlist::OnInvertSelection()
777 {
778     UINT iState;
779
780     for( long item = 0; item < ListView_GetItemCount( hListView ); item++ )
781     {
782         iState = ListView_GetItemState( hListView, item, LVIS_STATEIMAGEMASK );
783         ListView_SetItemState( hListView, item, iState ^ LVIS_SELECTED,
784                                LVIS_STATEIMAGEMASK );
785     }
786 }
787
788 void Playlist::OnEnableSelection()
789 {
790     playlist_t *p_playlist = (playlist_t *)
791         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
792     if( p_playlist == NULL ) return;
793
794     for( long item = ListView_GetItemCount( hListView ) - 1;
795          item >= 0; item-- )
796     {
797         if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
798         {
799             playlist_item_t *p_item =
800                 playlist_ItemGetByPos( p_playlist, item );
801             playlist_Enable( p_playlist, p_item );
802             UpdateItem( item );
803         }
804     }
805     vlc_object_release( p_playlist);
806 }
807
808 void Playlist::OnDisableSelection()
809 {
810     playlist_t *p_playlist = (playlist_t *)
811         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
812     if( p_playlist == NULL ) return;
813
814     for( long item = ListView_GetItemCount( hListView ) - 1;
815          item >= 0; item-- )
816     {
817         if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
818         {
819             /*XXX*/
820             playlist_item_t *p_item =
821                 playlist_ItemGetByPos( p_playlist, item );
822             playlist_Disable( p_playlist, p_item );
823             UpdateItem( item );
824         }
825     }
826     vlc_object_release( p_playlist);
827 }
828
829 void Playlist::OnSelectAll()
830 {
831     for( long item = 0; item < ListView_GetItemCount( hListView ); item++ )
832     {
833         ListView_SetItemState( hListView, item, LVIS_FOCUSED | LVIS_SELECTED,
834                                LVIS_STATEIMAGEMASK );
835     }
836 }
837
838 void Playlist::OnActivateItem( int i_item )
839 {
840     playlist_t *p_playlist = (playlist_t *)
841         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
842     if( p_playlist == NULL ) return;
843
844     playlist_Goto( p_playlist, i_item );
845
846     vlc_object_release( p_playlist );
847 }
848
849 void Playlist::ShowInfos( HWND hwnd, int i_item )
850 {
851     playlist_t *p_playlist = (playlist_t *)
852         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
853     if( p_playlist == NULL ) return;
854
855     vlc_mutex_lock( &p_playlist->object_lock);
856     playlist_item_t *p_item = playlist_ItemGetByPos( p_playlist, i_item );
857     vlc_mutex_unlock( &p_playlist->object_lock );
858
859     if( p_item )
860     {
861         ItemInfoDialog *iteminfo_dialog =
862             new ItemInfoDialog( p_intf, hInst, p_item );
863         CreateDialogBox( hwnd, iteminfo_dialog );                
864         UpdateItem( i_item );
865         delete iteminfo_dialog;
866     }
867
868     vlc_object_release( p_playlist );
869 }
870
871 /********************************************************************
872  * Move functions
873  ********************************************************************/
874 void Playlist::OnUp()
875 {
876     playlist_t *p_playlist = (playlist_t *)
877         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
878     if( p_playlist == NULL ) return;
879
880     /* We use the first selected item, so find it */
881     long i_item =
882         ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
883
884     if( i_item > 0 && i_item < p_playlist->i_size )
885     {
886         playlist_Move( p_playlist , i_item, i_item - 1);
887         if( i_item > 1 )
888         {
889             ListView_SetItemState( hListView, i_item - 1, LVIS_FOCUSED,
890                                    LVIS_STATEIMAGEMASK );
891         }
892         else
893         {
894             ListView_SetItemState( hListView, 0, LVIS_FOCUSED,
895                                    LVIS_STATEIMAGEMASK );
896         }
897     }
898     vlc_object_release( p_playlist );
899
900     return;
901 }
902
903 void Playlist::OnDown()
904 {
905     playlist_t *p_playlist = (playlist_t *)
906         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
907     if( p_playlist == NULL ) return;
908
909     /* We use the first selected item, so find it */
910     long i_item =
911         ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
912
913     if( i_item >= 0 && i_item < p_playlist->i_size - 1 )
914     {
915         playlist_Move( p_playlist , i_item, i_item + 2 );
916         ListView_SetItemState( hListView, i_item + 1, LVIS_FOCUSED,
917                                LVIS_STATEIMAGEMASK );
918     }
919     vlc_object_release( p_playlist );
920
921     return;
922 }
923
924 /**********************************************************************
925  * Playlist mode functions
926  **********************************************************************/
927 void Playlist::OnRandom()
928 {
929     vlc_value_t val;
930     int bState = SendMessage( hwndTB, TB_GETSTATE, Random_Event, 0 ); 
931     val.b_bool = (bState & TBSTATE_CHECKED) ? VLC_TRUE : VLC_FALSE;
932
933     playlist_t *p_playlist = (playlist_t *)
934         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
935     if( p_playlist == NULL ) return;
936
937     var_Set( p_playlist , "random", val );
938     vlc_object_release( p_playlist );
939 }
940
941 void Playlist::OnLoop ()
942 {
943     vlc_value_t val;
944     int bState = SendMessage( hwndTB, TB_GETSTATE, Loop_Event, 0 ); 
945     val.b_bool = (bState & TBSTATE_CHECKED) ? VLC_TRUE : VLC_FALSE;
946
947     playlist_t *p_playlist = (playlist_t *)
948         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
949     if( p_playlist == NULL ) return;
950
951     var_Set( p_playlist , "loop", val );
952     vlc_object_release( p_playlist );
953 }
954
955 void Playlist::OnRepeat ()
956 {
957     vlc_value_t val;
958     int bState = SendMessage( hwndTB, TB_GETSTATE, Repeat_Event, 0 );  
959     val.b_bool = (bState & TBSTATE_CHECKED) ? VLC_TRUE : VLC_FALSE;
960
961     playlist_t *p_playlist = (playlist_t *)
962         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
963     if( p_playlist == NULL ) return;
964
965     var_Set( p_playlist , "repeat", val );
966     vlc_object_release( p_playlist );
967 }
968
969 /********************************************************************
970  * Sorting functions
971  ********************************************************************/
972 void Playlist::OnSort( UINT event )
973 {
974     playlist_t *p_playlist = (playlist_t *)
975         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
976     if( p_playlist == NULL ) return;
977
978     switch( event )
979     {
980     case ID_SORT_TITLE:
981         playlist_SortTitle( p_playlist , ORDER_NORMAL );
982         break;
983     case ID_SORT_RTITLE:
984         playlist_SortTitle( p_playlist , ORDER_REVERSE );
985         break;
986     case ID_SORT_AUTHOR:
987         playlist_SortAuthor(p_playlist , ORDER_NORMAL );
988         break;
989     case ID_SORT_RAUTHOR:
990         playlist_SortAuthor( p_playlist , ORDER_REVERSE );
991         break;
992     case ID_SORT_SHUFFLE:
993         playlist_Sort( p_playlist , SORT_RANDOM, ORDER_NORMAL );
994         break;
995     }
996
997     vlc_object_release( p_playlist );
998
999     b_need_update = VLC_TRUE;
1000
1001     return;
1002 }
1003
1004 void Playlist::OnColSelect( int iSubItem )
1005 {
1006     playlist_t *p_playlist = (playlist_t *)
1007         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1008     if( p_playlist == NULL ) return;
1009
1010     switch( iSubItem )
1011     {
1012     case 0:
1013         if( i_title_sorted != 1 )
1014         {
1015             playlist_SortTitle( p_playlist, ORDER_NORMAL );
1016             i_title_sorted = 1;
1017         }
1018         else
1019         {
1020             playlist_SortTitle( p_playlist, ORDER_REVERSE );
1021             i_title_sorted = -1;
1022         }
1023         break;
1024     case 1:
1025         if( i_author_sorted != 1 )
1026         {
1027             playlist_SortAuthor( p_playlist, ORDER_NORMAL );
1028             i_author_sorted = 1;
1029         }
1030         else
1031         {
1032             playlist_SortAuthor( p_playlist, ORDER_REVERSE );
1033             i_author_sorted = -1;
1034         }
1035         break;
1036     default:
1037         break;
1038     }
1039
1040     vlc_object_release( p_playlist );
1041
1042     b_need_update = VLC_TRUE;
1043
1044     return;
1045 }
1046
1047 /*****************************************************************************
1048  * Popup management functions
1049  *****************************************************************************/
1050 void Playlist::OnPopupPlay()
1051 {
1052     int i_popup_item =
1053         ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1054
1055     playlist_t *p_playlist = (playlist_t *)
1056         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1057     if( p_playlist == NULL ) return;
1058
1059     if( i_popup_item != -1 )
1060     {
1061         playlist_Goto( p_playlist, i_popup_item );
1062     }
1063
1064     vlc_object_release( p_playlist );
1065 }
1066
1067 void Playlist::OnPopupDel()
1068 {
1069     int i_popup_item =
1070         ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1071
1072     DeleteItem( i_popup_item );
1073 }
1074
1075 void Playlist::OnPopupEna()
1076 {
1077     int i_popup_item =
1078         ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1079
1080     playlist_t *p_playlist = (playlist_t *)
1081         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1082     if( p_playlist == NULL ) return;
1083
1084     playlist_item_t *p_item =
1085         playlist_ItemGetByPos( p_playlist, i_popup_item );
1086
1087     if( p_playlist->pp_items[i_popup_item]->b_enabled )
1088         //playlist_IsEnabled( p_playlist, i_popup_item ) )
1089     {
1090         playlist_Disable( p_playlist, p_item );
1091     }
1092     else
1093     {
1094         playlist_Enable( p_playlist, p_item );
1095     }
1096
1097     vlc_object_release( p_playlist);
1098     UpdateItem( i_popup_item );
1099 }
1100
1101 void Playlist::OnPopupInfo( HWND hwnd )
1102 {
1103     int i_popup_item =
1104         ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1105
1106     ShowInfos( hwnd, i_popup_item );
1107 }