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;
634 while( ( p_child = playlist_GetNextLeaf( p_playlist, p_root, p_child, FALSE, FALSE ) ) )
642 ListView_InsertItem( hListView, &lv );
643 ListView_SetItemText( hListView, lv.iItem, 0,
644 _FROMMB(p_child->p_input->psz_name) );
646 UpdateItem( p_child->i_id );
651 ListView_SetItemState( hListView, i_focused, LVIS_FOCUSED |
652 LVIS_SELECTED, LVIS_STATEIMAGEMASK )
654 ListView_SetItemState( hListView, i_focused, LVIS_FOCUSED,
655 LVIS_STATEIMAGEMASK );
657 pl_Release( p_intf );
660 /**********************************************************************
661 * Update one playlist item
662 **********************************************************************/
663 void Playlist::UpdateItem( int i )
665 playlist_t *p_playlist = pl_Hold( p_intf );
667 if( p_playlist == NULL ) return;
670 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i );
675 pl_Release( p_intf );
679 ListView_SetItemText( hListView, i, 0, _FROMMB(p_item->p_input->psz_name) );
681 ListView_SetItemText( hListView, i, 1,
682 _FROMMB( input_item_GetInfo( p_item->p_input,
683 _("General") , _("Author") ) ) );
685 char psz_duration[MSTRTIME_MAX_SIZE];
686 mtime_t dur = input_item_GetDuration( p_item->p_input );
689 if( dur != -1 ) secstotimestr( psz_duration, dur/1000000 );
690 else memcpy( psz_duration , "-:--:--", sizeof("-:--:--") );
692 ListView_SetItemText( hListView, i, 2, _FROMMB(psz_duration) );
694 pl_Release( p_intf );
697 /**********************************************************************
699 **********************************************************************/
700 void Playlist::DeleteItem( int item )
702 playlist_t *p_playlist = pl_Hold( p_intf );
703 if( p_playlist == NULL ) return;
705 playlist_DeleteFromInput( p_playlist, item, FALSE );
706 ListView_DeleteItem( hListView, item );
708 pl_Release( p_intf );
711 /**********************************************************************
713 **********************************************************************/
714 static void OnOpenCB( intf_dialog_args_t *p_arg )
716 intf_thread_t *p_intf = (intf_thread_t *)p_arg->p_arg;
718 if( p_arg->i_results && p_arg->psz_results[0] )
720 playlist_t * p_playlist = pl_Hold( p_intf );
724 playlist_Import( p_playlist, p_arg->psz_results[0] );
725 pl_Release( p_intf );
730 void Playlist::OnOpen()
732 char *psz_filters ="All playlists|*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u";
734 intf_dialog_args_t *p_arg =
735 (intf_dialog_args_t *)malloc( sizeof(intf_dialog_args_t) );
736 memset( p_arg, 0, sizeof(intf_dialog_args_t) );
738 p_arg->psz_title = strdup( "Open playlist" );
739 p_arg->psz_extensions = strdup( psz_filters );
740 p_arg->p_arg = p_intf;
741 p_arg->pf_callback = OnOpenCB;
743 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_GENERIC, 0, p_arg);
746 static void OnSaveCB( intf_dialog_args_t *p_arg )
748 intf_thread_t *p_intf = (intf_thread_t *)p_arg->p_arg;
750 if( p_arg->i_results && p_arg->psz_results[0] )
752 playlist_t * p_playlist = pl_Hold( p_intf );
757 char *psz_ext = strrchr( p_arg->psz_results[0], '.' );
759 if( psz_ext && !strcmp( psz_ext, ".pls") )
760 psz_export = "export-pls";
761 else psz_export = "export-m3u";
763 playlist_Export( p_playlist, p_arg->psz_results[0], p_playlist->p_local_onelevel, psz_export );
764 pl_Release( p_intf );
769 void Playlist::OnSave()
771 char *psz_filters ="M3U file|*.m3u|PLS file|*.pls";
773 intf_dialog_args_t *p_arg =
774 (intf_dialog_args_t *)malloc( sizeof(intf_dialog_args_t) );
775 memset( p_arg, 0, sizeof(intf_dialog_args_t) );
777 p_arg->psz_title = strdup( "Save playlist" );
778 p_arg->psz_extensions = strdup( psz_filters );
779 p_arg->b_save = true;
780 p_arg->p_arg = p_intf;
781 p_arg->pf_callback = OnSaveCB;
783 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_GENERIC,
787 /**********************************************************************
788 * Selection functions
789 **********************************************************************/
790 void Playlist::OnDeleteSelection()
792 /* Delete from the end to the beginning, to avoid a shift of indices */
793 for( long item = ((int) ListView_GetItemCount( hListView ) - 1);
796 if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
803 void Playlist::OnInvertSelection()
807 for( long item = 0; item < ListView_GetItemCount( hListView ); item++ )
809 iState = ListView_GetItemState( hListView, item, LVIS_STATEIMAGEMASK );
810 ListView_SetItemState( hListView, item, iState ^ LVIS_SELECTED,
811 LVIS_STATEIMAGEMASK );
815 void Playlist::OnEnableSelection()
817 playlist_t *p_playlist = pl_Hold( p_intf );
818 if( p_playlist == NULL ) return;
820 for( long item = ListView_GetItemCount( hListView ) - 1;
823 if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
826 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item );
827 p_item->i_flags ^= PLAYLIST_DBL_FLAG;
832 pl_Release( p_intf );
835 void Playlist::OnDisableSelection()
837 playlist_t *p_playlist = pl_Hold( p_intf );
838 if( p_playlist == NULL ) return;
840 for( long item = ListView_GetItemCount( hListView ) - 1;
843 if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
846 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item );
847 p_item->i_flags |= PLAYLIST_DBL_FLAG;
852 pl_Release( p_intf );
855 void Playlist::OnSelectAll()
857 for( long item = 0; item < ListView_GetItemCount( hListView ); item++ )
859 ListView_SetItemState( hListView, item, LVIS_FOCUSED | LVIS_SELECTED,
860 LVIS_STATEIMAGEMASK );
864 void Playlist::OnActivateItem( int i_item )
866 playlist_t *p_playlist = pl_Hold( p_intf );
867 if( p_playlist == NULL ) return;
869 playlist_Skip( p_playlist, i_item - p_playlist->i_current_index );
871 pl_Release( p_intf );
874 void Playlist::ShowInfos( HWND hwnd, int i_item )
876 playlist_t *p_playlist = pl_Hold( p_intf );
877 if( p_playlist == NULL ) return;
880 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_item );
883 ItemInfoDialog *iteminfo_dialog =
884 new ItemInfoDialog( p_intf, this, hInst, p_item );
886 CreateDialogBox( hwnd, iteminfo_dialog );
887 UpdateItem( i_item );
888 delete iteminfo_dialog;
891 pl_Release( p_intf );
894 /********************************************************************
896 ********************************************************************/
897 void Playlist::OnUp()
899 playlist_t *p_playlist = pl_Hold( p_intf );
900 if( p_playlist == NULL ) return;
902 /* We use the first selected item, so find it */
904 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
906 if( i_item > 0 && i_item < playlist_CurrentSize( p_playlist ) )
908 playlist_Prev( p_playlist );
911 ListView_SetItemState( hListView, i_item - 1, LVIS_FOCUSED,
912 LVIS_STATEIMAGEMASK );
916 ListView_SetItemState( hListView, 0, LVIS_FOCUSED,
917 LVIS_STATEIMAGEMASK );
920 pl_Release( p_intf );
925 void Playlist::OnDown()
927 playlist_t *p_playlist = pl_Hold( p_intf );
928 if( p_playlist == NULL ) return;
930 /* We use the first selected item, so find it */
932 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
934 if( i_item >= 0 && i_item < playlist_CurrentSize( p_playlist ) - 1 )
936 playlist_Next( p_playlist );
937 ListView_SetItemState( hListView, i_item + 1, LVIS_FOCUSED,
938 LVIS_STATEIMAGEMASK );
940 pl_Release( p_intf );
945 /**********************************************************************
946 * Playlist mode functions
947 **********************************************************************/
948 void Playlist::OnRandom()
951 int bState = SendMessage( hwndTB, TB_GETSTATE, Random_Event, 0 );
952 val.b_bool = (bState & TBSTATE_CHECKED) ? true : false;
954 playlist_t *p_playlist = pl_Hold( p_intf );
955 if( p_playlist == NULL ) return;
957 var_Set( p_playlist , "random", val );
958 pl_Release( p_intf );
961 void Playlist::OnLoop ()
964 int bState = SendMessage( hwndTB, TB_GETSTATE, Loop_Event, 0 );
965 val.b_bool = (bState & TBSTATE_CHECKED) ? true : false;
967 playlist_t *p_playlist = pl_Hold( p_intf );
968 if( p_playlist == NULL ) return;
970 var_Set( p_playlist , "loop", val );
971 pl_Release( p_intf );
974 void Playlist::OnRepeat ()
977 int bState = SendMessage( hwndTB, TB_GETSTATE, Repeat_Event, 0 );
978 val.b_bool = (bState & TBSTATE_CHECKED) ? true : false;
980 playlist_t *p_playlist = pl_Hold( p_intf );
981 if( p_playlist == NULL ) return;
983 var_Set( p_playlist , "repeat", val );
984 pl_Release( p_intf );
987 /********************************************************************
989 ********************************************************************/
990 void Playlist::OnSort( UINT event )
992 playlist_t *p_playlist = pl_Hold( p_intf );
993 if( p_playlist == NULL ) return;
998 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
999 SORT_TITLE, ORDER_NORMAL);
1001 case ID_SORT_RTITLE:
1002 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1003 SORT_TITLE, ORDER_REVERSE );
1005 case ID_SORT_AUTHOR:
1006 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1007 SORT_ARTIST, ORDER_NORMAL);
1009 case ID_SORT_RAUTHOR:
1010 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1011 SORT_ARTIST, ORDER_REVERSE);
1013 case ID_SORT_SHUFFLE:
1014 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1015 SORT_RANDOM, ORDER_NORMAL);
1019 pl_Release( p_intf );
1021 b_need_update = true;
1026 void Playlist::OnColSelect( int iSubItem )
1028 playlist_t *p_playlist = pl_Hold( p_intf );
1029 if( p_playlist == NULL ) return;
1034 if( i_title_sorted != 1 )
1036 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1037 SORT_TITLE, ORDER_NORMAL);
1042 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1043 SORT_TITLE, ORDER_REVERSE );
1044 i_title_sorted = -1;
1048 if( i_author_sorted != 1 )
1050 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1051 SORT_ARTIST, ORDER_NORMAL);
1052 i_author_sorted = 1;
1056 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1057 SORT_ARTIST, ORDER_REVERSE);
1058 i_author_sorted = -1;
1065 pl_Release( p_intf );
1067 b_need_update = true;
1072 /*****************************************************************************
1073 * Popup management functions
1074 *****************************************************************************/
1075 void Playlist::OnPopupPlay()
1078 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1080 playlist_t *p_playlist = pl_Hold( p_intf );
1081 if( p_playlist == NULL ) return;
1083 if( i_popup_item != -1 )
1085 playlist_Skip( p_playlist, i_popup_item - p_playlist->i_current_index );
1088 pl_Release( p_intf );
1091 void Playlist::OnPopupDel()
1094 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1096 DeleteItem( i_popup_item );
1099 void Playlist::OnPopupEna()
1102 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1104 playlist_t *p_playlist = pl_Hold( p_intf );
1105 if( p_playlist == NULL ) return;
1108 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_popup_item );
1110 if( !(p_playlist->items.p_elems[i_popup_item]->i_flags & PLAYLIST_DBL_FLAG) )
1111 //playlist_IsEnabled( p_playlist, i_popup_item ) )
1113 p_item->i_flags |= PLAYLIST_DBL_FLAG;
1117 p_item->i_flags ^= PLAYLIST_DBL_FLAG;
1121 pl_Release( p_intf );
1122 UpdateItem( i_popup_item );
1125 void Playlist::OnPopupInfo( HWND hwnd )
1128 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1130 ShowInfos( hwnd, i_popup_item );