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_Yield( 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_Yield( 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 );
529 playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
530 (int)lplvcd->nmcd.dwItemSpec, FALSE );
533 pl_Release( p_intf );
534 return CDRF_DODEFAULT;
536 if( p_item->i_flags & PLAYLIST_DBL_FLAG )
538 lplvcd->clrText = RGB(192,192,192);
539 pl_Release( p_intf );
542 pl_Release( p_intf );
545 return CDRF_DODEFAULT;
548 /**********************************************************************
549 * Handles the display of the "floating" popup
550 **********************************************************************/
551 void Playlist::HandlePopupMenu( HWND hwnd, POINT point )
553 HMENU hMenuTrackPopup;
555 // Create the popup menu.
556 hMenuTrackPopup = CreatePopupMenu();
558 // Append some items.
559 AppendMenu( hMenuTrackPopup, MF_STRING, PopupPlay_Event, _T("Play") );
560 AppendMenu( hMenuTrackPopup, MF_STRING, PopupDel_Event, _T("Delete") );
561 AppendMenu( hMenuTrackPopup, MF_STRING, PopupEna_Event,
562 _T("Toggle enabled") );
563 AppendMenu( hMenuTrackPopup, MF_STRING, PopupInfo_Event, _T("Info") );
565 /* Draw and track the "floating" popup */
566 TrackPopupMenu( hMenuTrackPopup, 0, point.x, point.y, 0, hwnd, NULL );
568 /* Destroy the menu since were are done with it. */
569 DestroyMenu( hMenuTrackPopup );
572 /**********************************************************************
574 **********************************************************************/
575 void Playlist::ShowPlaylist( bool b_show )
577 if( b_show ) Rebuild();
581 /**********************************************************************
582 * Update the playlist
583 **********************************************************************/
584 void Playlist::UpdatePlaylist()
589 b_need_update = false;
592 playlist_t *p_playlist = pl_Yield( p_intf );
593 if( p_playlist == NULL ) return;
595 /* Update the colour of items */
598 if( p_intf->p_sys->i_playing != playlist_CurrentSize( p_playlist ) )
600 // p_playlist->i_index in RED
603 // if exists, p_intf->p_sys->i_playing in BLACK
604 p_intf->p_sys->i_playing = p_playlist->i_current_index;
608 pl_Release( p_intf );
611 /**********************************************************************
612 * Rebuild the playlist
613 **********************************************************************/
614 void Playlist::Rebuild()
616 playlist_t *p_playlist = pl_Yield( p_intf );
617 if( p_playlist == NULL ) return;
620 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
622 /* Clear the list... */
623 ListView_DeleteAllItems( hListView );
625 /* ...and rebuild it */
627 playlist_item_t * p_root = p_playlist->p_local_onelevel;
628 playlist_item_t * p_child = NULL;
630 for( int i = 0; i < playlist_NodeChildrenCount( p_playlist, p_root ); i++ )
632 p_child = playlist_GetNextLeaf( p_playlist, p_root, p_child, FALSE, FALSE);
639 ListView_InsertItem( hListView, &lv );
640 ListView_SetItemText( hListView, lv.iItem, 0,
641 _FROMMB(p_child->p_input->psz_name) );
643 UpdateItem( p_child->i_id );
648 ListView_SetItemState( hListView, i_focused, LVIS_FOCUSED |
649 LVIS_SELECTED, LVIS_STATEIMAGEMASK )
651 ListView_SetItemState( hListView, i_focused, LVIS_FOCUSED,
652 LVIS_STATEIMAGEMASK );
654 pl_Release( p_intf );
657 /**********************************************************************
658 * Update one playlist item
659 **********************************************************************/
660 void Playlist::UpdateItem( int i )
662 playlist_t *p_playlist = pl_Yield( p_intf );
664 if( p_playlist == NULL ) return;
666 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i, FALSE );
670 pl_Release( p_intf );
674 ListView_SetItemText( hListView, i, 0, _FROMMB(p_item->p_input->psz_name) );
676 ListView_SetItemText( hListView, i, 1,
677 _FROMMB( input_item_GetInfo( p_item->p_input,
678 _("General") , _("Author") ) ) );
680 char psz_duration[MSTRTIME_MAX_SIZE];
681 mtime_t dur = input_item_GetDuration( p_item->p_input );
683 if( dur != -1 ) secstotimestr( psz_duration, dur/1000000 );
684 else memcpy( psz_duration , "-:--:--", sizeof("-:--:--") );
686 ListView_SetItemText( hListView, i, 2, _FROMMB(psz_duration) );
688 pl_Release( p_intf );
691 /**********************************************************************
693 **********************************************************************/
694 void Playlist::DeleteItem( int item )
696 playlist_t *p_playlist = pl_Yield( p_intf );
697 if( p_playlist == NULL ) return;
699 playlist_DeleteFromInput( p_playlist, item, FALSE );
700 ListView_DeleteItem( hListView, item );
702 pl_Release( p_intf );
705 /**********************************************************************
707 **********************************************************************/
708 static void OnOpenCB( intf_dialog_args_t *p_arg )
710 intf_thread_t *p_intf = (intf_thread_t *)p_arg->p_arg;
712 if( p_arg->i_results && p_arg->psz_results[0] )
714 playlist_t * p_playlist = pl_Yield( p_intf );
718 playlist_Import( p_playlist, p_arg->psz_results[0] );
719 pl_Release( p_intf );
724 void Playlist::OnOpen()
726 char *psz_filters ="All playlists|*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u";
728 intf_dialog_args_t *p_arg =
729 (intf_dialog_args_t *)malloc( sizeof(intf_dialog_args_t) );
730 memset( p_arg, 0, sizeof(intf_dialog_args_t) );
732 p_arg->psz_title = strdup( "Open playlist" );
733 p_arg->psz_extensions = strdup( psz_filters );
734 p_arg->p_arg = p_intf;
735 p_arg->pf_callback = OnOpenCB;
737 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_GENERIC, 0, p_arg);
740 static void OnSaveCB( intf_dialog_args_t *p_arg )
742 intf_thread_t *p_intf = (intf_thread_t *)p_arg->p_arg;
744 if( p_arg->i_results && p_arg->psz_results[0] )
746 playlist_t * p_playlist = pl_Yield( p_intf );
751 char *psz_ext = strrchr( p_arg->psz_results[0], '.' );
753 if( psz_ext && !strcmp( psz_ext, ".pls") )
754 psz_export = "export-pls";
755 else psz_export = "export-m3u";
757 playlist_Export( p_playlist, p_arg->psz_results[0], p_playlist->p_local_onelevel, psz_export );
758 pl_Release( p_intf );
763 void Playlist::OnSave()
765 char *psz_filters ="M3U file|*.m3u|PLS file|*.pls";
767 intf_dialog_args_t *p_arg =
768 (intf_dialog_args_t *)malloc( sizeof(intf_dialog_args_t) );
769 memset( p_arg, 0, sizeof(intf_dialog_args_t) );
771 p_arg->psz_title = strdup( "Save playlist" );
772 p_arg->psz_extensions = strdup( psz_filters );
773 p_arg->b_save = true;
774 p_arg->p_arg = p_intf;
775 p_arg->pf_callback = OnSaveCB;
777 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_GENERIC,
781 /**********************************************************************
782 * Selection functions
783 **********************************************************************/
784 void Playlist::OnDeleteSelection()
786 /* Delete from the end to the beginning, to avoid a shift of indices */
787 for( long item = ((int) ListView_GetItemCount( hListView ) - 1);
790 if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
797 void Playlist::OnInvertSelection()
801 for( long item = 0; item < ListView_GetItemCount( hListView ); item++ )
803 iState = ListView_GetItemState( hListView, item, LVIS_STATEIMAGEMASK );
804 ListView_SetItemState( hListView, item, iState ^ LVIS_SELECTED,
805 LVIS_STATEIMAGEMASK );
809 void Playlist::OnEnableSelection()
811 playlist_t *p_playlist = pl_Yield( p_intf );
812 if( p_playlist == NULL ) return;
814 for( long item = ListView_GetItemCount( hListView ) - 1;
817 if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
819 playlist_item_t *p_item =
820 playlist_ItemGetById( p_playlist, item, FALSE );
821 p_item->i_flags ^= PLAYLIST_DBL_FLAG;
825 pl_Release( p_intf );
828 void Playlist::OnDisableSelection()
830 playlist_t *p_playlist = pl_Yield( p_intf );
831 if( p_playlist == NULL ) return;
833 for( long item = ListView_GetItemCount( hListView ) - 1;
836 if( ListView_GetItemState( hListView, item, LVIS_SELECTED ) )
839 playlist_item_t *p_item =
840 playlist_ItemGetById( p_playlist, item, FALSE );
841 p_item->i_flags |= PLAYLIST_DBL_FLAG;
845 pl_Release( p_intf );
848 void Playlist::OnSelectAll()
850 for( long item = 0; item < ListView_GetItemCount( hListView ); item++ )
852 ListView_SetItemState( hListView, item, LVIS_FOCUSED | LVIS_SELECTED,
853 LVIS_STATEIMAGEMASK );
857 void Playlist::OnActivateItem( int i_item )
859 playlist_t *p_playlist = pl_Yield( p_intf );
860 if( p_playlist == NULL ) return;
862 playlist_Skip( p_playlist, i_item - p_playlist->i_current_index );
864 pl_Release( p_intf );
867 void Playlist::ShowInfos( HWND hwnd, int i_item )
869 playlist_t *p_playlist = pl_Yield( p_intf );
870 if( p_playlist == NULL ) return;
873 playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_item, true );
878 ItemInfoDialog *iteminfo_dialog =
879 new ItemInfoDialog( p_intf, this, hInst, p_item );
880 CreateDialogBox( hwnd, iteminfo_dialog );
881 UpdateItem( i_item );
882 delete iteminfo_dialog;
885 pl_Release( p_intf );
888 /********************************************************************
890 ********************************************************************/
891 void Playlist::OnUp()
893 playlist_t *p_playlist = pl_Yield( p_intf );
894 if( p_playlist == NULL ) return;
896 /* We use the first selected item, so find it */
898 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
900 if( i_item > 0 && i_item < playlist_CurrentSize( p_playlist ) )
902 playlist_Prev( p_playlist );
905 ListView_SetItemState( hListView, i_item - 1, LVIS_FOCUSED,
906 LVIS_STATEIMAGEMASK );
910 ListView_SetItemState( hListView, 0, LVIS_FOCUSED,
911 LVIS_STATEIMAGEMASK );
914 pl_Release( p_intf );
919 void Playlist::OnDown()
921 playlist_t *p_playlist = pl_Yield( p_intf );
922 if( p_playlist == NULL ) return;
924 /* We use the first selected item, so find it */
926 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
928 if( i_item >= 0 && i_item < playlist_CurrentSize( p_playlist ) - 1 )
930 playlist_Next( p_playlist );
931 ListView_SetItemState( hListView, i_item + 1, LVIS_FOCUSED,
932 LVIS_STATEIMAGEMASK );
934 pl_Release( p_intf );
939 /**********************************************************************
940 * Playlist mode functions
941 **********************************************************************/
942 void Playlist::OnRandom()
945 int bState = SendMessage( hwndTB, TB_GETSTATE, Random_Event, 0 );
946 val.b_bool = (bState & TBSTATE_CHECKED) ? true : false;
948 playlist_t *p_playlist = pl_Yield( p_intf );
949 if( p_playlist == NULL ) return;
951 var_Set( p_playlist , "random", val );
952 pl_Release( p_intf );
955 void Playlist::OnLoop ()
958 int bState = SendMessage( hwndTB, TB_GETSTATE, Loop_Event, 0 );
959 val.b_bool = (bState & TBSTATE_CHECKED) ? true : false;
961 playlist_t *p_playlist = pl_Yield( p_intf );
962 if( p_playlist == NULL ) return;
964 var_Set( p_playlist , "loop", val );
965 pl_Release( p_intf );
968 void Playlist::OnRepeat ()
971 int bState = SendMessage( hwndTB, TB_GETSTATE, Repeat_Event, 0 );
972 val.b_bool = (bState & TBSTATE_CHECKED) ? true : false;
974 playlist_t *p_playlist = pl_Yield( p_intf );
975 if( p_playlist == NULL ) return;
977 var_Set( p_playlist , "repeat", val );
978 pl_Release( p_intf );
981 /********************************************************************
983 ********************************************************************/
984 void Playlist::OnSort( UINT event )
986 playlist_t *p_playlist = pl_Yield( p_intf );
987 if( p_playlist == NULL ) return;
992 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
993 SORT_TITLE, ORDER_NORMAL);
996 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
997 SORT_TITLE, ORDER_REVERSE );
1000 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1001 SORT_ARTIST, ORDER_NORMAL);
1003 case ID_SORT_RAUTHOR:
1004 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1005 SORT_ARTIST, ORDER_REVERSE);
1007 case ID_SORT_SHUFFLE:
1008 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1009 SORT_RANDOM, ORDER_NORMAL);
1013 pl_Release( p_intf );
1015 b_need_update = true;
1020 void Playlist::OnColSelect( int iSubItem )
1022 playlist_t *p_playlist = pl_Yield( p_intf );
1023 if( p_playlist == NULL ) return;
1028 if( i_title_sorted != 1 )
1030 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1031 SORT_TITLE, ORDER_NORMAL);
1036 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1037 SORT_TITLE, ORDER_REVERSE );
1038 i_title_sorted = -1;
1042 if( i_author_sorted != 1 )
1044 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1045 SORT_ARTIST, ORDER_NORMAL);
1046 i_author_sorted = 1;
1050 playlist_RecursiveNodeSort(p_playlist , p_playlist->p_root_onelevel,
1051 SORT_ARTIST, ORDER_REVERSE);
1052 i_author_sorted = -1;
1059 pl_Release( p_intf );
1061 b_need_update = true;
1066 /*****************************************************************************
1067 * Popup management functions
1068 *****************************************************************************/
1069 void Playlist::OnPopupPlay()
1072 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1074 playlist_t *p_playlist = pl_Yield( p_intf );
1075 if( p_playlist == NULL ) return;
1077 if( i_popup_item != -1 )
1079 playlist_Skip( p_playlist, i_popup_item - p_playlist->i_current_index );
1082 pl_Release( p_intf );
1085 void Playlist::OnPopupDel()
1088 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1090 DeleteItem( i_popup_item );
1093 void Playlist::OnPopupEna()
1096 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1098 playlist_t *p_playlist = pl_Yield( p_intf );
1099 if( p_playlist == NULL ) return;
1101 playlist_item_t *p_item =
1102 playlist_ItemGetById( p_playlist, i_popup_item, FALSE );
1104 if( !(p_playlist->items.p_elems[i_popup_item]->i_flags & PLAYLIST_DBL_FLAG) )
1105 //playlist_IsEnabled( p_playlist, i_popup_item ) )
1107 p_item->i_flags |= PLAYLIST_DBL_FLAG;
1111 p_item->i_flags ^= PLAYLIST_DBL_FLAG;
1114 pl_Release( p_intf );
1115 UpdateItem( i_popup_item );
1118 void Playlist::OnPopupInfo( HWND hwnd )
1121 ListView_GetNextItem( hListView, -1, LVIS_SELECTED | LVNI_ALL );
1123 ShowInfos( hwnd, i_popup_item );