1 /*****************************************************************************
2 * playlist.cpp : WinCE gui plugin for VLC
3 *****************************************************************************
4 * Copyright (C) 2000-2004 the VideoLAN team
7 * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
8 * Gildas Bazin <gbazin@videolan.org>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_interface.h>
34 #include <vlc_playlist.h>
42 #define TEXTMAXBUF 512 // at least 500
45 #define LONG2POINT(l, pt) ((pt).x = (SHORT)LOWORD(l), (pt).y = (SHORT)HIWORD(l))
47 #define NUMIMAGES 11 // Number of buttons in the toolbar
48 #define IMAGEWIDTH 16 // Width of the buttons in the toolbar
49 #define IMAGEHEIGHT 16 // Height of the buttons in the toolbar
50 #define BUTTONWIDTH 0 // Width of the button images in the toolbar
51 #define BUTTONHEIGHT 0 // Height of the button images in the toolbar
52 #define ID_TOOLBAR 2000 // Identifier of the main tool bar
69 #define HELP_OPENPL _T("Open playlist")
70 #define HELP_SAVEPL _T("Save playlist")
71 #define HELP_ADDFILE _T("Add File")
72 #define HELP_ADDMRL _T("Add MRL")
73 #define HELP_DELETE _T("Delete selection")
74 #define HELP_INFOS _T("Item info")
75 #define HELP_UP _T("Up")
76 #define HELP_DOWN _T("Down")
77 #define HELP_RANDOM _T("Random")
78 #define HELP_LOOP _T("Repeat all")
79 #define HELP_REPEAT _T("Repeat one")
81 // The TBBUTTON structure contains information the toolbar buttons.
82 static TBBUTTON tbButton2[] =
84 {0, ID_MANAGE_OPENPL, TBSTATE_ENABLED, TBSTYLE_BUTTON },
85 {1, ID_MANAGE_SAVEPL, TBSTATE_ENABLED, TBSTYLE_BUTTON },
86 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP },
87 {2, ID_MANAGE_ADDFILE, TBSTATE_ENABLED, TBSTYLE_BUTTON },
88 {3, ID_MANAGE_ADDMRL, TBSTATE_ENABLED, TBSTYLE_BUTTON },
89 {4, ID_SEL_DELETE, TBSTATE_ENABLED, TBSTYLE_BUTTON },
90 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP },
91 {5, Infos_Event, TBSTATE_ENABLED, TBSTYLE_BUTTON },
92 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP },
93 {6, Up_Event, TBSTATE_ENABLED, TBSTYLE_BUTTON },
94 {7, Down_Event, TBSTATE_ENABLED, TBSTYLE_BUTTON },
95 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP },
96 {8, Random_Event, TBSTATE_ENABLED, TBSTYLE_CHECK },
97 {9, Loop_Event, TBSTATE_ENABLED, TBSTYLE_CHECK },
98 {10, Repeat_Event, TBSTATE_ENABLED, TBSTYLE_CHECK }
102 TCHAR * szToolTips2[] =
117 /*****************************************************************************
119 *****************************************************************************/
121 /*****************************************************************************
123 *****************************************************************************/
124 Playlist::Playlist( intf_thread_t *p_intf, CBaseWindow *p_parent,
126 : CBaseWindow( p_intf, p_parent, h_inst )
128 /* Initializations */
133 b_need_update = true;
136 /***********************************************************************
142 ***********************************************************************/
143 static HWND CreateMenuBar( HWND hwnd, HINSTANCE hInst )
147 memset( &mbi, 0, sizeof(SHMENUBARINFO) );
148 mbi.cbSize = sizeof(SHMENUBARINFO);
149 mbi.hwndParent = hwnd;
150 mbi.hInstRes = hInst;
151 mbi.nToolBarId = IDR_MENUBAR2;
153 if( !SHCreateMenuBar( &mbi ) )
155 MessageBox(hwnd, _T("SHCreateMenuBar Failed"), _T("Error"), MB_OK);
160 tbbi.cbSize = sizeof(tbbi);
161 tbbi.dwMask = TBIF_LPARAM;
163 SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_MANAGE, (LPARAM)&tbbi );
164 HMENU hmenu_file = (HMENU)tbbi.lParam;
165 RemoveMenu( hmenu_file, 0, MF_BYPOSITION );
166 SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_SORT, (LPARAM)&tbbi );
167 HMENU hmenu_sort = (HMENU)tbbi.lParam;
168 RemoveMenu( hmenu_sort, 0, MF_BYPOSITION );
169 SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_SEL, (LPARAM)&tbbi );
170 HMENU hmenu_sel = (HMENU)tbbi.lParam;
171 RemoveMenu( hmenu_sel, 0, MF_BYPOSITION );
174 HMENU hmenu_file = CreatePopupMenu();
175 HMENU hmenu_sort = CreatePopupMenu();
176 HMENU hmenu_sel = CreatePopupMenu();
179 AppendMenu( hmenu_file, MF_STRING, ID_MANAGE_ADDFILE,
180 _T("&Add File...") );
181 AppendMenu( hmenu_file, MF_STRING, ID_MANAGE_ADDDIRECTORY,
182 _T("Add Directory...") );
183 AppendMenu( hmenu_file, MF_STRING, ID_MANAGE_ADDMRL,
185 AppendMenu( hmenu_file, MF_SEPARATOR, 0, 0 );
186 AppendMenu( hmenu_file, MF_STRING, ID_MANAGE_OPENPL,
187 _T("Open &Playlist") );
188 AppendMenu( hmenu_file, MF_STRING, ID_MANAGE_SAVEPL,
189 _T("Save Playlist") );
191 AppendMenu( hmenu_sort, MF_STRING, ID_SORT_TITLE,
192 _T("Sort by &title") );
193 AppendMenu( hmenu_sort, MF_STRING, ID_SORT_RTITLE,
194 _T("&Reverse sort by title") );
195 AppendMenu( hmenu_sort, MF_SEPARATOR, 0, 0 );
196 AppendMenu( hmenu_sort, MF_STRING, ID_SORT_AUTHOR,
197 _T("Sort by &author") );
198 AppendMenu( hmenu_sort, MF_STRING, ID_SORT_RAUTHOR,
199 _T("Reverse sort by &author") );
200 AppendMenu( hmenu_sort, MF_SEPARATOR, 0, 0 );
201 AppendMenu( hmenu_sort, MF_STRING, ID_SORT_SHUFFLE,
202 _T("&Shuffle Playlist") );
204 AppendMenu( hmenu_sel, MF_STRING, ID_SEL_ENABLE,
206 AppendMenu( hmenu_sel, MF_STRING, ID_SEL_DISABLE,
208 AppendMenu( hmenu_sel, MF_SEPARATOR, 0, 0 );
209 AppendMenu( hmenu_sel, MF_STRING, ID_SEL_INVERT,
211 AppendMenu( hmenu_sel, MF_STRING, ID_SEL_DELETE,
213 AppendMenu( hmenu_sel, MF_SEPARATOR, 0, 0 );
214 AppendMenu( hmenu_sel, MF_STRING, ID_SEL_SELECTALL,
222 HMENU hmenu = CreateMenu();
224 AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)hmenu_file, _T("Manage") );
225 AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)hmenu_sort, _T("Sort") );
226 AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)hmenu_sel, _T("Selection") );
228 SetMenu( hwnd, hmenu );
234 /***********************************************************************
239 Processes messages sent to the main window.
240 ***********************************************************************/
241 LRESULT Playlist::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
245 INITCOMMONCONTROLSEX iccex;
250 playlist_t *p_playlist;
255 shidi.dwMask = SHIDIM_FLAGS;
256 shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN |
257 SHIDIF_FULLSCREENNOMENUBAR;//SHIDIF_SIZEDLGFULLSCREEN;
259 SHInitDialog( &shidi );
261 hwndCB = CreateMenuBar( hwnd, hInst );
263 iccex.dwSize = sizeof (INITCOMMONCONTROLSEX);
264 iccex.dwICC = ICC_BAR_CLASSES;
266 // Registers TOOLBAR control classes from the common control dll
267 InitCommonControlsEx (&iccex);
269 // Create the toolbar control.
270 dwStyle = WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS |
271 WS_EX_OVERLAPPEDWINDOW | CCS_NOPARENTALIGN;
273 hwndTB = CreateToolbarEx( hwnd, dwStyle, 0, NUMIMAGES,
274 hInst, IDB_BITMAP3, tbButton2,
275 sizeof (tbButton2) / sizeof (TBBUTTON),
276 BUTTONWIDTH, BUTTONHEIGHT,
277 IMAGEWIDTH, IMAGEHEIGHT, sizeof(TBBUTTON) );
280 // Add ToolTips to the toolbar.
281 SendMessage( hwndTB, TB_SETTOOLTIPS, (WPARAM) NUMIMAGES,
282 (LPARAM)szToolTips2 );
284 // Reposition the toolbar.
285 GetClientRect( hwnd, &rect );
286 GetWindowRect( hwndTB, &rectTB );
287 MoveWindow( hwndTB, rect.left, rect.top - 2, rect.right - rect.left,
288 MENU_HEIGHT /*rectTB.bottom - rectTB.top */, TRUE);
290 // random, loop, repeat buttons states
292 p_playlist = pl_Hold( p_intf );
293 if( !p_playlist ) break;
295 var_Get( p_playlist , "random", &val );
296 bState = val.b_bool ? TBSTATE_CHECKED : 0;
297 SendMessage( hwndTB, TB_SETSTATE, Random_Event,
298 MAKELONG(bState | TBSTATE_ENABLED, 0) );
299 var_Get( p_playlist , "loop", &val );
300 bState = val.b_bool ? TBSTATE_CHECKED : 0;
301 SendMessage( hwndTB, TB_SETSTATE, Loop_Event,
302 MAKELONG(bState | TBSTATE_ENABLED, 0) );
303 var_Get( p_playlist , "repeat", &val );
304 bState = val.b_bool ? TBSTATE_CHECKED : 0;
305 SendMessage( hwndTB, TB_SETSTATE, Repeat_Event,
306 MAKELONG(bState | TBSTATE_ENABLED, 0) );
307 pl_Release( p_intf );
309 GetClientRect( hwnd, &rect );
310 hListView = CreateWindow( WC_LISTVIEW, NULL, WS_VISIBLE | WS_CHILD |
311 LVS_REPORT | LVS_SHOWSELALWAYS | WS_VSCROLL | WS_HSCROLL,
312 rect.left, rect.top + 2*(MENU_HEIGHT+1), rect.right - rect.left,
313 rect.bottom - ( rect.top + 2*MENU_HEIGHT) - MENU_HEIGHT,
314 hwnd, NULL, hInst, NULL );
315 ListView_SetExtendedListViewStyle( hListView, LVS_EX_FULLROWSELECT );
318 lv.mask = LVCF_WIDTH | LVCF_FMT | LVCF_TEXT;
319 lv.fmt = LVCFMT_LEFT ;
320 GetClientRect( hwnd, &rect );
322 lv.pszText = _T("Name");
324 ListView_InsertColumn( hListView, 0, &lv);
326 lv.pszText = _T("Author");
328 ListView_InsertColumn( hListView, 1, &lv);
329 lv.cx = rect.right - rect.left - 180;
330 lv.pszText = _T("Duration");
332 ListView_InsertColumn( hListView, 2, &lv);
334 SetTimer( hwnd, 1, 500 /*milliseconds*/, NULL );
342 EndDialog( hwnd, LOWORD( wp ) );
346 SHSipPreference( hwnd, SIP_DOWN );
347 SHFullScreen( hwnd, SHFS_HIDESIPBUTTON );
354 EndDialog( hwnd, LOWORD( wp ) );
357 case ID_MANAGE_OPENPL:
359 b_need_update = true;
362 case ID_MANAGE_SAVEPL:
366 case ID_MANAGE_ADDFILE:
367 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_SIMPLE,
369 b_need_update = true;
372 case ID_MANAGE_ADDDIRECTORY:
373 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_DIRECTORY,
375 b_need_update = true;
378 case ID_MANAGE_ADDMRL:
379 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE, 0, 0 );
380 b_need_update = true;
385 b_need_update = true;
390 b_need_update = true;
395 b_need_update = true;
400 b_need_update = true;
416 OnSort( ID_SORT_TITLE );
420 OnSort( ID_SORT_RTITLE );
424 OnSort( ID_SORT_AUTHOR );
427 case ID_SORT_RAUTHOR:
428 OnSort( ID_SORT_RAUTHOR );
431 case ID_SORT_SHUFFLE:
432 OnSort( ID_SORT_SHUFFLE );
440 OnDisableSelection();
447 case ID_SEL_SELECTALL:
451 case PopupPlay_Event:
453 b_need_update = true;
458 b_need_update = true;
463 b_need_update = true;
466 case PopupInfo_Event:
468 b_need_update = true;
477 if( ( ((LPNMHDR)lp)->hwndFrom == hListView ) &&
478 ( ((LPNMHDR)lp)->code == NM_CUSTOMDRAW ) )
480 SetWindowLong( hwnd, DWL_MSGRESULT,
481 (LONG)ProcessCustomDraw(lp) );
483 else if( ( ((LPNMHDR)lp)->hwndFrom == hListView ) &&
484 ( ((LPNMHDR)lp)->code == GN_CONTEXTMENU ) )
486 HandlePopupMenu( hwnd, ((PNMRGINFO)lp)->ptAction );
488 else if( ( ((LPNMHDR)lp)->hwndFrom == hListView ) &&
489 ( ((LPNMHDR)lp)->code == LVN_COLUMNCLICK ) )
491 OnColSelect( ((LPNMLISTVIEW)lp)->iSubItem );
493 else if( ( ((LPNMHDR)lp)->hwndFrom == hListView ) &&
494 ( ((LPNMHDR)lp)->code == LVN_ITEMACTIVATE ) )
496 OnActivateItem( ((LPNMLISTVIEW)lp)->iSubItem );
501 // the message was not processed
502 // indicate if the base class handled it
509 LRESULT Playlist::ProcessCustomDraw( LPARAM lParam )
511 LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
513 switch( lplvcd->nmcd.dwDrawStage )
515 case CDDS_PREPAINT : //Before the paint cycle begins
516 //request notifications for individual listview items
517 return CDRF_NOTIFYITEMDRAW;
519 case CDDS_ITEMPREPAINT: //Before an item is drawn
520 playlist_t *p_playlist = pl_Hold( p_intf );
521 if( p_playlist == NULL ) return CDRF_DODEFAULT;
522 if( (int)lplvcd->nmcd.dwItemSpec == p_playlist->i_current_index )
524 lplvcd->clrText = RGB(255,0,0);
525 pl_Release( p_intf );
530 playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
531 (int)lplvcd->nmcd.dwItemSpec );
535 pl_Release( p_intf );
536 return CDRF_DODEFAULT;
538 if( p_item->i_flags & PLAYLIST_DBL_FLAG )
540 lplvcd->clrText = RGB(192,192,192);
542 pl_Release( p_intf );
546 pl_Release( p_intf );
549 return CDRF_DODEFAULT;
552 /**********************************************************************
553 * Handles the display of the "floating" popup
554 **********************************************************************/
555 void Playlist::HandlePopupMenu( HWND hwnd, POINT point )
557 HMENU hMenuTrackPopup;
559 // Create the popup menu.
560 hMenuTrackPopup = CreatePopupMenu();
562 // Append some items.
563 AppendMenu( hMenuTrackPopup, MF_STRING, PopupPlay_Event, _T("Play") );
564 AppendMenu( hMenuTrackPopup, MF_STRING, PopupDel_Event, _T("Delete") );
565 AppendMenu( hMenuTrackPopup, MF_STRING, PopupEna_Event,
566 _T("Toggle enabled") );
567 AppendMenu( hMenuTrackPopup, MF_STRING, PopupInfo_Event, _T("Info") );
569 /* Draw and track the "floating" popup */
570 TrackPopupMenu( hMenuTrackPopup, 0, point.x, point.y, 0, hwnd, NULL );
572 /* Destroy the menu since were are done with it. */
573 DestroyMenu( hMenuTrackPopup );
576 /**********************************************************************
578 **********************************************************************/
579 void Playlist::ShowPlaylist( bool b_show )
581 if( b_show ) Rebuild();
585 /**********************************************************************
586 * Update the playlist
587 **********************************************************************/
588 void Playlist::UpdatePlaylist()
593 b_need_update = false;
596 playlist_t *p_playlist = pl_Hold( p_intf );
597 if( p_playlist == NULL ) return;
599 /* Update the colour of items */
602 if( p_intf->p_sys->i_playing != playlist_CurrentSize( p_playlist ) )
604 // p_playlist->i_index in RED
607 // if exists, p_intf->p_sys->i_playing in BLACK
608 p_intf->p_sys->i_playing = p_playlist->i_current_index;
612 pl_Release( p_intf );
615 /**********************************************************************
616 * Rebuild the playlist
617 **********************************************************************/
618 void Playlist::Rebuild()
620 playlist_t *p_playlist = pl_Hold( p_intf );
621 if( p_playlist == NULL ) return;
624 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
626 /* Clear the list... */
627 ListView_DeleteAllItems( hListView );
629 /* ...and rebuild it */
631 playlist_item_t * p_root = p_playlist->p_local_onelevel;
632 playlist_item_t * p_child = NULL;
636 while( ( p_child = playlist_GetNextLeaf( p_playlist, p_root, p_child, FALSE, FALSE ) ) )
644 ListView_InsertItem( hListView, &lv );
645 ListView_SetItemText( hListView, lv.iItem, 0,
646 _FROMMB(p_child->p_input->psz_name) );
648 UpdateItem( p_child->i_id );
654 ListView_SetItemState( hListView, i_focused, LVIS_FOCUSED |
655 LVIS_SELECTED, LVIS_STATEIMAGEMASK )
657 ListView_SetItemState( hListView, i_focused, LVIS_FOCUSED,
658 LVIS_STATEIMAGEMASK );
660 pl_Release( p_intf );
663 /**********************************************************************
664 * Update one playlist item
665 **********************************************************************/
666 void Playlist::UpdateItem( int i )
668 playlist_t *p_playlist = pl_Hold( p_intf );
670 if( p_playlist == NULL ) return;
673 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i );
678 pl_Release( p_intf );
682 ListView_SetItemText( hListView, i, 0, _FROMMB(p_item->p_input->psz_name) );
684 ListView_SetItemText( hListView, i, 1,
685 _FROMMB( input_item_GetInfo( p_item->p_input,
686 _("General") , _("Author") ) ) );
688 char psz_duration[MSTRTIME_MAX_SIZE];
689 mtime_t dur = input_item_GetDuration( p_item->p_input );
692 if( dur != -1 ) secstotimestr( psz_duration, dur/1000000 );
693 else memcpy( psz_duration , "-:--:--", sizeof("-:--:--") );
695 ListView_SetItemText( hListView, i, 2, _FROMMB(psz_duration) );
697 pl_Release( p_intf );
700 /**********************************************************************
702 **********************************************************************/
703 void Playlist::DeleteItem( input_item_t *item )
705 playlist_t *p_playlist = pl_Hold( p_intf );
706 if( p_playlist == NULL ) return;
708 playlist_DeleteFromInput( p_playlist, item, FALSE );
709 ListView_DeleteItem( hListView, item );
711 pl_Release( p_intf );
714 /**********************************************************************
716 **********************************************************************/
717 static void OnOpenCB( intf_dialog_args_t *p_arg )
719 intf_thread_t *p_intf = (intf_thread_t *)p_arg->p_arg;
721 if( p_arg->i_results && p_arg->psz_results[0] )
723 playlist_t * p_playlist = pl_Hold( p_intf );
727 playlist_Import( p_playlist, p_arg->psz_results[0] );
728 pl_Release( p_intf );
733 void Playlist::OnOpen()
735 char *psz_filters ="All playlists|*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u";
737 intf_dialog_args_t *p_arg =
738 (intf_dialog_args_t *)malloc( sizeof(intf_dialog_args_t) );
739 memset( p_arg, 0, sizeof(intf_dialog_args_t) );
741 p_arg->psz_title = strdup( "Open playlist" );
742 p_arg->psz_extensions = strdup( psz_filters );
743 p_arg->p_arg = p_intf;
744 p_arg->pf_callback = OnOpenCB;
746 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_GENERIC, 0, p_arg);
749 static void OnSaveCB( intf_dialog_args_t *p_arg )
751 intf_thread_t *p_intf = (intf_thread_t *)p_arg->p_arg;
753 if( p_arg->i_results && p_arg->psz_results[0] )
755 playlist_t * p_playlist = pl_Hold( p_intf );
760 char *psz_ext = strrchr( p_arg->psz_results[0], '.' );
762 if( psz_ext && !strcmp( psz_ext, ".pls") )
763 psz_export = "export-pls";
764 else psz_export = "export-m3u";
766 playlist_Export( p_playlist, p_arg->psz_results[0], p_playlist->p_local_onelevel, psz_export );
767 pl_Release( p_intf );
772 void Playlist::OnSave()
774 char *psz_filters ="M3U file|*.m3u|PLS file|*.pls";
776 intf_dialog_args_t *p_arg =
777 (intf_dialog_args_t *)malloc( sizeof(intf_dialog_args_t) );
778 memset( p_arg, 0, sizeof(intf_dialog_args_t) );
780 p_arg->psz_title = strdup( "Save playlist" );
781 p_arg->psz_extensions = strdup( psz_filters );
782 p_arg->b_save = true;
783 p_arg->p_arg = p_intf;
784 p_arg->pf_callback = OnSaveCB;
786 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_GENERIC,
790 /**********************************************************************
791 * Selection functions
792 **********************************************************************/
793 void Playlist::OnDeleteSelection()
795 /* Delete from the end to the beginning, to avoid a shift of indices */
796 for( long item = ((int) ListView_GetItemCount( hListView ) - 1);
799 if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
806 void Playlist::OnInvertSelection()
810 for( long item = 0; item < ListView_GetItemCount( hListView ); item++ )
812 iState = ListView_GetItemState( hListView, item, LVIS_STATEIMAGEMASK );
813 ListView_SetItemState( hListView, item, iState ^ LVIS_SELECTED,
814 LVIS_STATEIMAGEMASK );
818 void Playlist::OnEnableSelection()
820 playlist_t *p_playlist = pl_Hold( p_intf );
821 if( p_playlist == NULL ) return;
823 for( long item = ListView_GetItemCount( hListView ) - 1;
826 if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
829 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item );
830 p_item->i_flags ^= PLAYLIST_DBL_FLAG;
835 pl_Release( p_intf );
838 void Playlist::OnDisableSelection()
840 playlist_t *p_playlist = pl_Hold( p_intf );
841 if( p_playlist == NULL ) return;
843 for( long item = ListView_GetItemCount( hListView ) - 1;
846 if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
849 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item );
850 p_item->i_flags |= PLAYLIST_DBL_FLAG;
855 pl_Release( p_intf );
858 void Playlist::OnSelectAll()
860 for( long item = 0; item < ListView_GetItemCount( hListView ); item++ )
862 ListView_SetItemState( hListView, item, LVIS_FOCUSED | LVIS_SELECTED,
863 LVIS_STATEIMAGEMASK );
867 void Playlist::OnActivateItem( int i_item )
869 playlist_t *p_playlist = pl_Hold( p_intf );
870 if( p_playlist == NULL ) return;
872 playlist_Skip( p_playlist, i_item - p_playlist->i_current_index );
874 pl_Release( p_intf );
877 void Playlist::ShowInfos( HWND hwnd, int i_item )
879 playlist_t *p_playlist = pl_Hold( p_intf );
880 if( p_playlist == NULL ) return;
883 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_item );
886 ItemInfoDialog *iteminfo_dialog =
887 new ItemInfoDialog( p_intf, this, hInst, p_item );
889 CreateDialogBox( hwnd, iteminfo_dialog );
890 UpdateItem( i_item );
891 delete iteminfo_dialog;
894 pl_Release( p_intf );
897 /********************************************************************
899 ********************************************************************/
900 void Playlist::OnUp()
902 playlist_t *p_playlist = pl_Hold( p_intf );
903 if( p_playlist == NULL ) return;
905 /* We use the first selected item, so find it */
907 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
909 if( i_item > 0 && i_item < playlist_CurrentSize( p_playlist ) )
911 playlist_Prev( p_playlist );
914 ListView_SetItemState( hListView, i_item - 1, LVIS_FOCUSED,
915 LVIS_STATEIMAGEMASK );
919 ListView_SetItemState( hListView, 0, LVIS_FOCUSED,
920 LVIS_STATEIMAGEMASK );
923 pl_Release( p_intf );
928 void Playlist::OnDown()
930 playlist_t *p_playlist = pl_Hold( p_intf );
931 if( p_playlist == NULL ) return;
933 /* We use the first selected item, so find it */
935 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
937 if( i_item >= 0 && i_item < playlist_CurrentSize( p_playlist ) - 1 )
939 playlist_Next( p_playlist );
940 ListView_SetItemState( hListView, i_item + 1, LVIS_FOCUSED,
941 LVIS_STATEIMAGEMASK );
943 pl_Release( p_intf );
948 /**********************************************************************
949 * Playlist mode functions
950 **********************************************************************/
951 void Playlist::OnRandom()
954 int bState = SendMessage( hwndTB, TB_GETSTATE, Random_Event, 0 );
955 val.b_bool = (bState & TBSTATE_CHECKED) ? true : false;
957 playlist_t *p_playlist = pl_Hold( p_intf );
958 if( p_playlist == NULL ) return;
960 var_Set( p_playlist , "random", val );
961 pl_Release( p_intf );
964 void Playlist::OnLoop ()
967 int bState = SendMessage( hwndTB, TB_GETSTATE, Loop_Event, 0 );
968 val.b_bool = (bState & TBSTATE_CHECKED) ? true : false;
970 playlist_t *p_playlist = pl_Hold( p_intf );
971 if( p_playlist == NULL ) return;
973 var_Set( p_playlist , "loop", val );
974 pl_Release( p_intf );
977 void Playlist::OnRepeat ()
980 int bState = SendMessage( hwndTB, TB_GETSTATE, Repeat_Event, 0 );
981 val.b_bool = (bState & TBSTATE_CHECKED) ? true : false;
983 playlist_t *p_playlist = pl_Hold( p_intf );
984 if( p_playlist == NULL ) return;
986 var_Set( p_playlist , "repeat", val );
987 pl_Release( p_intf );
990 /********************************************************************
992 ********************************************************************/
993 void Playlist::OnSort( UINT event )
995 playlist_t *p_playlist = pl_Hold( p_intf );
996 if( p_playlist == NULL ) return;
1001 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1002 SORT_TITLE, ORDER_NORMAL);
1004 case ID_SORT_RTITLE:
1005 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1006 SORT_TITLE, ORDER_REVERSE );
1008 case ID_SORT_AUTHOR:
1009 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1010 SORT_ARTIST, ORDER_NORMAL);
1012 case ID_SORT_RAUTHOR:
1013 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1014 SORT_ARTIST, ORDER_REVERSE);
1016 case ID_SORT_SHUFFLE:
1017 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1018 SORT_RANDOM, ORDER_NORMAL);
1022 pl_Release( p_intf );
1024 b_need_update = true;
1029 void Playlist::OnColSelect( int iSubItem )
1031 playlist_t *p_playlist = pl_Hold( p_intf );
1032 if( p_playlist == NULL ) return;
1037 if( i_title_sorted != 1 )
1039 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1040 SORT_TITLE, ORDER_NORMAL);
1045 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1046 SORT_TITLE, ORDER_REVERSE );
1047 i_title_sorted = -1;
1051 if( i_author_sorted != 1 )
1053 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1054 SORT_ARTIST, ORDER_NORMAL);
1055 i_author_sorted = 1;
1059 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1060 SORT_ARTIST, ORDER_REVERSE);
1061 i_author_sorted = -1;
1068 pl_Release( p_intf );
1070 b_need_update = true;
1075 /*****************************************************************************
1076 * Popup management functions
1077 *****************************************************************************/
1078 void Playlist::OnPopupPlay()
1081 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1083 playlist_t *p_playlist = pl_Hold( p_intf );
1084 if( p_playlist == NULL ) return;
1086 if( i_popup_item != -1 )
1088 playlist_Skip( p_playlist, i_popup_item - p_playlist->i_current_index );
1091 pl_Release( p_intf );
1094 void Playlist::OnPopupDel()
1097 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1099 DeleteItem( i_popup_item );
1102 void Playlist::OnPopupEna()
1105 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1107 playlist_t *p_playlist = pl_Hold( p_intf );
1108 if( p_playlist == NULL ) return;
1111 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_popup_item );
1113 if( !(p_playlist->items.p_elems[i_popup_item]->i_flags & PLAYLIST_DBL_FLAG) )
1114 //playlist_IsEnabled( p_playlist, i_popup_item ) )
1116 p_item->i_flags |= PLAYLIST_DBL_FLAG;
1120 p_item->i_flags ^= PLAYLIST_DBL_FLAG;
1124 pl_Release( p_intf );
1125 UpdateItem( i_popup_item );
1128 void Playlist::OnPopupInfo( HWND hwnd )
1131 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1133 ShowInfos( hwnd, i_popup_item );