changed: New label formatting that more logically drops separators.
[xbmc:xbmc-antiquated.git] / xbmc / GUIWindowMusicPlaylist.cpp
1 /*
2  *      Copyright (C) 2005-2007 Team XboxMediaCenter
3  *      http://www.xboxmediacenter.com
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with GNU Make; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "stdafx.h"
23 #include "GUIWindowMusicPlayList.h"
24 #include "GUIDialogSmartPlaylistEditor.h"
25 #include "util.h"
26 #include "PlayListM3U.h"
27 #include "application.h"
28 #include "playlistplayer.h"
29 #include "PartyModeManager.h"
30 #include "utils/LabelFormatter.h"
31
32 using namespace PLAYLIST;
33
34 #define CONTROL_BTNVIEWASICONS     2
35 #define CONTROL_BTNSORTBY          3
36 #define CONTROL_BTNSORTASC         4
37 #define CONTROL_LIST              50
38 #define CONTROL_THUMBS            51
39 #define CONTROL_LABELFILES        12
40
41 #define CONTROL_BTNSHUFFLE    20
42 #define CONTROL_BTNSAVE      21
43 #define CONTROL_BTNCLEAR     22
44
45 #define CONTROL_BTNPLAY      23
46 #define CONTROL_BTNNEXT      24
47 #define CONTROL_BTNPREVIOUS    25
48 #define CONTROL_BTNREPEAT     26
49
50 CGUIWindowMusicPlayList::CGUIWindowMusicPlayList(void)
51     : CGUIWindowMusicBase(WINDOW_MUSIC_PLAYLIST, "MyMusicPlaylist.xml")
52 {
53   m_musicInfoLoader.SetObserver(this);
54   m_musicInfoLoader.SetPriority(THREAD_PRIORITY_LOWEST);
55   m_movingFrom = -1;
56 }
57
58 CGUIWindowMusicPlayList::~CGUIWindowMusicPlayList(void)
59 {
60 }
61
62 bool CGUIWindowMusicPlayList::OnMessage(CGUIMessage& message)
63 {
64   switch ( message.GetMessage() )
65   {
66   case GUI_MSG_PLAYLISTPLAYER_REPEAT:
67     {
68       UpdateButtons();
69     }
70     break;
71
72   case GUI_MSG_PLAYLISTPLAYER_RANDOM:
73   case GUI_MSG_PLAYLIST_CHANGED:
74     {
75       // global playlist changed outside playlist window
76       UpdateButtons();
77       Update(m_vecItems.m_strPath);
78
79       if (m_viewControl.HasControl(m_iLastControl) && m_vecItems.Size() <= 0)
80       {
81         m_iLastControl = CONTROL_BTNVIEWASICONS;
82         SET_CONTROL_FOCUS(m_iLastControl, 0);
83       }
84
85     }
86     break;
87
88   case GUI_MSG_WINDOW_DEINIT:
89     {
90       if (m_musicInfoLoader.IsLoading())
91         m_musicInfoLoader.StopThread();
92
93       m_movingFrom = -1;
94     }
95     break;
96
97   case GUI_MSG_WINDOW_INIT:
98     {
99       // Setup item cache for tagloader
100       m_musicInfoLoader.UseCacheOnHD("Z:\\MusicPlaylist.fi");
101
102       m_vecItems.m_strPath="playlistmusic://";
103
104       // updatebuttons is called in here
105       if (!CGUIWindowMusicBase::OnMessage(message))
106         return false;
107
108       if (m_vecItems.Size() <= 0)
109       {
110         m_iLastControl = CONTROL_BTNVIEWASICONS;
111         SET_CONTROL_FOCUS(m_iLastControl, 0);
112       }
113
114       if (g_application.IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_MUSIC)
115       {
116         int iSong = g_playlistPlayer.GetCurrentSong();
117         if (iSong >= 0 && iSong <= m_vecItems.Size())
118           m_viewControl.SetSelectedItem(iSong);
119       }
120
121       return true;
122     }
123     break;
124
125   case GUI_MSG_CLICKED:
126     {
127       int iControl = message.GetSenderId();
128       if (iControl == CONTROL_BTNSHUFFLE)
129       {
130         if (!g_partyModeManager.IsEnabled())
131         {
132           g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, !(g_playlistPlayer.IsShuffled(PLAYLIST_MUSIC)));
133           g_stSettings.m_bMyMusicPlaylistShuffle = g_playlistPlayer.IsShuffled(PLAYLIST_MUSIC);
134           g_settings.Save();
135           UpdateButtons();
136           Update(m_vecItems.m_strPath);
137         }
138       }
139       else if (iControl == CONTROL_BTNSAVE)
140       {
141         if (m_musicInfoLoader.IsLoading()) // needed since we destroy m_vecitems to save memory
142           m_musicInfoLoader.StopThread();
143
144         SavePlayList();
145       }
146       else if (iControl == CONTROL_BTNCLEAR)
147       {
148         if (m_musicInfoLoader.IsLoading())
149           m_musicInfoLoader.StopThread();
150
151         ClearPlayList();
152       }
153       else if (iControl == CONTROL_BTNPLAY)
154       {
155         m_guiState->SetPlaylistDirectory("playlistmusic://");
156         g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_MUSIC);
157         g_playlistPlayer.Reset();
158         g_playlistPlayer.Play(m_viewControl.GetSelectedItem());
159         UpdateButtons();
160       }
161       else if (iControl == CONTROL_BTNNEXT)
162       {
163         g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_MUSIC);
164         g_playlistPlayer.PlayNext();
165       }
166       else if (iControl == CONTROL_BTNPREVIOUS)
167       {
168         g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_MUSIC);
169         g_playlistPlayer.PlayPrevious();
170       }
171       else if (iControl == CONTROL_BTNREPEAT)
172       {
173         // increment repeat state
174         PLAYLIST::REPEAT_STATE state = g_playlistPlayer.GetRepeat(PLAYLIST_MUSIC);
175         if (state == PLAYLIST::REPEAT_NONE)
176           g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, PLAYLIST::REPEAT_ALL);
177         else if (state == PLAYLIST::REPEAT_ALL)
178           g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, PLAYLIST::REPEAT_ONE);
179         else
180           g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, PLAYLIST::REPEAT_NONE);
181
182         // save settings
183         g_stSettings.m_bMyMusicPlaylistRepeat = g_playlistPlayer.GetRepeat(PLAYLIST_MUSIC) == PLAYLIST::REPEAT_ALL;
184         g_settings.Save();
185
186         UpdateButtons();
187       }
188       else if (m_viewControl.HasControl(iControl))
189       {
190         int iAction = message.GetParam1();
191         int iItem = m_viewControl.GetSelectedItem();
192         if (iAction == ACTION_DELETE_ITEM || iAction == ACTION_MOUSE_MIDDLE_CLICK)
193         {
194           RemovePlayListItem(iItem);
195           MarkPlaying();
196         }
197       }
198     }
199     break;
200
201   }
202   return CGUIWindowMusicBase::OnMessage(message);
203 }
204
205 bool CGUIWindowMusicPlayList::OnAction(const CAction &action)
206 {
207   if (action.wID == ACTION_PARENT_DIR)
208   {
209     // Playlist has no parent dirs
210     return true;
211   }
212   if (action.wID == ACTION_SHOW_PLAYLIST)
213   {
214     m_gWindowManager.ChangeActiveWindow(WINDOW_MUSIC);
215     return true;
216   }
217   if ((action.wID == ACTION_MOVE_ITEM_UP) || (action.wID == ACTION_MOVE_ITEM_DOWN))
218   {
219     int iItem = -1;
220     int iFocusedControl = GetFocusedControlID();
221     if (m_viewControl.HasControl(iFocusedControl))
222       iItem = m_viewControl.GetSelectedItem();
223     OnMove(iItem, action.wID);
224     return true;
225   }
226   return CGUIWindowMusicBase::OnAction(action);
227 }
228
229 bool CGUIWindowMusicPlayList::MoveCurrentPlayListItem(int iItem, int iAction, bool bUpdate /* = true */)
230 {
231   int iSelected = iItem;
232   int iNew = iSelected;
233   if (iAction == ACTION_MOVE_ITEM_UP)
234     iNew--;
235   else
236     iNew++;
237
238   // is the currently playing item affected?
239   bool bFixCurrentSong = false;
240   if ((g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_MUSIC) && (g_application.IsPlayingAudio()) &&
241     ((g_playlistPlayer.GetCurrentSong() == iSelected) || (g_playlistPlayer.GetCurrentSong() == iNew)))
242     bFixCurrentSong = true;
243
244   CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_MUSIC);
245   if (playlist.Swap(iSelected, iNew))
246   {
247     // Correct the current playing song in playlistplayer
248     if (bFixCurrentSong)
249     {
250       int iCurrentSong = g_playlistPlayer.GetCurrentSong();
251       if (iSelected == iCurrentSong)
252         iCurrentSong = iNew;
253       else if (iNew == iCurrentSong)
254         iCurrentSong = iSelected;
255       g_playlistPlayer.SetCurrentSong(iCurrentSong);
256     }
257
258     if (bUpdate)
259       Update(m_vecItems.m_strPath);
260     return true;
261   }
262
263   return false;
264 }
265
266 void CGUIWindowMusicPlayList::SavePlayList()
267 {
268   CStdString strNewFileName;
269   if (CGUIDialogKeyboard::ShowAndGetInput(strNewFileName, g_localizeStrings.Get(16012), false))
270   {
271     // need 2 rename it
272     CStdString strFolder, strPath;
273     strFolder = CUtil::MusicPlaylistsLocation();
274     CUtil::RemoveIllegalChars( strNewFileName );
275     strNewFileName += ".m3u";
276     CUtil::AddFileToFolder(strFolder, strNewFileName, strPath);
277
278     // get selected item
279     int iItem = m_viewControl.GetSelectedItem();
280     CStdString strSelectedItem = "";
281     if (iItem >= 0 && iItem < m_vecItems.Size())
282     {
283       CFileItem* pItem = m_vecItems[iItem];
284       if (!pItem->IsParentFolder())
285       {
286         GetDirectoryHistoryString(pItem, strSelectedItem);
287       }
288     }
289
290     CStdString strOldDirectory = m_vecItems.m_strPath;
291     m_history.SetSelectedItem(strSelectedItem, strOldDirectory);
292
293     CPlayListM3U playlist;
294     for (int i = 0; i < (int)m_vecItems.Size(); ++i)
295     {
296       CFileItem* pItem = m_vecItems[i];
297       CPlayList::CPlayListItem newItem;
298       newItem.SetFileName(pItem->m_strPath);
299       newItem.SetDescription(pItem->GetLabel());
300       if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->GetDuration())
301         newItem.SetDuration(pItem->GetMusicInfoTag()->GetDuration());
302       else
303         newItem.SetDuration(0);
304
305       //  Musicdatabase items should contain the real path instead of a musicdb url
306       //  otherwise the user can't save and reuse the playlist when the musicdb gets deleted
307       if (pItem->IsMusicDb())
308         newItem.m_strPath=pItem->GetMusicInfoTag()->GetURL();
309
310       playlist.Add(newItem);
311       m_vecItems.Remove(i--);
312     }
313     CLog::Log(LOGDEBUG, "Saving music playlist: [%s]", strPath.c_str());
314     playlist.Save(strPath);
315     Update(m_vecItems.m_strPath); // need to update
316   }
317 }
318
319 void CGUIWindowMusicPlayList::ClearPlayList()
320 {
321   ClearFileItems();
322   g_playlistPlayer.ClearPlaylist(PLAYLIST_MUSIC);
323   if (g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_MUSIC)
324   {
325     g_playlistPlayer.Reset();
326     g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
327   }
328   Update(m_vecItems.m_strPath);
329   SET_CONTROL_FOCUS(CONTROL_BTNVIEWASICONS, 0);
330 }
331
332 void CGUIWindowMusicPlayList::RemovePlayListItem(int iItem)
333 {
334   if (iItem < 0 || iItem > m_vecItems.Size()) return;
335
336   // The current playing song can't be removed
337   if (g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_MUSIC && g_application.IsPlayingAudio()
338       && g_playlistPlayer.GetCurrentSong() == iItem)
339     return ;
340
341   g_playlistPlayer.GetPlaylist(PLAYLIST_MUSIC).Remove(iItem);
342
343   // Correct the current playing song in playlistplayer
344   if (g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_MUSIC && g_application.IsPlayingAudio())
345   {
346     int iCurrentSong = g_playlistPlayer.GetCurrentSong();
347     if (iItem <= iCurrentSong)
348     {
349       iCurrentSong--;
350       g_playlistPlayer.SetCurrentSong(iCurrentSong);
351     }
352   }
353
354   Update(m_vecItems.m_strPath);
355
356   if (m_vecItems.Size() <= 0)
357   {
358     SET_CONTROL_FOCUS(CONTROL_BTNVIEWASICONS, 0);
359   }
360   else
361   {
362     m_viewControl.SetSelectedItem(iItem);
363   }
364
365   g_partyModeManager.OnSongChange();
366 }
367
368 void CGUIWindowMusicPlayList::UpdateButtons()
369 {
370   CGUIWindowMusicBase::UpdateButtons();
371
372   // Update playlist buttons
373   if (m_vecItems.Size() && !g_partyModeManager.IsEnabled())
374   {
375     CONTROL_ENABLE(CONTROL_BTNSHUFFLE);
376     CONTROL_ENABLE(CONTROL_BTNSAVE);
377     CONTROL_ENABLE(CONTROL_BTNCLEAR);
378     CONTROL_ENABLE(CONTROL_BTNREPEAT);
379     CONTROL_ENABLE(CONTROL_BTNPLAY);
380
381     if (g_application.IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_MUSIC)
382     {
383       CONTROL_ENABLE(CONTROL_BTNNEXT);
384       CONTROL_ENABLE(CONTROL_BTNPREVIOUS);
385     }
386     else
387     {
388       CONTROL_DISABLE(CONTROL_BTNNEXT);
389       CONTROL_DISABLE(CONTROL_BTNPREVIOUS);
390     }
391
392     // disable repeat options if clear on end is enabled
393     if (g_guiSettings.GetBool("mymusic.clearplaylistsonend"))
394     {
395       g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, PLAYLIST::REPEAT_NONE);
396       CONTROL_DISABLE(CONTROL_BTNREPEAT);
397     }
398   }
399   else
400   {
401     // disable buttons if party mode is enabled too
402     CONTROL_DISABLE(CONTROL_BTNSHUFFLE);
403     CONTROL_DISABLE(CONTROL_BTNSAVE);
404     CONTROL_DISABLE(CONTROL_BTNCLEAR);
405     CONTROL_DISABLE(CONTROL_BTNREPEAT);
406     CONTROL_DISABLE(CONTROL_BTNPLAY);
407     CONTROL_DISABLE(CONTROL_BTNNEXT);
408     CONTROL_DISABLE(CONTROL_BTNPREVIOUS);
409   }
410
411   // update buttons
412   CONTROL_DESELECT(CONTROL_BTNSHUFFLE);
413   if (g_playlistPlayer.IsShuffled(PLAYLIST_MUSIC))
414     CONTROL_SELECT(CONTROL_BTNSHUFFLE);
415
416   // update repeat button
417   int iRepeat = 595 + g_playlistPlayer.GetRepeat(PLAYLIST_MUSIC);
418   SET_CONTROL_LABEL(CONTROL_BTNREPEAT, g_localizeStrings.Get(iRepeat));
419
420   // Update object count label
421   int iItems = m_vecItems.Size();
422   if (iItems)
423   {
424     CFileItem* pItem = m_vecItems[0];
425     if (pItem->IsParentFolder()) iItems--;
426   }
427   CStdString items;
428   items.Format("%i %s", iItems, g_localizeStrings.Get(127).c_str());
429   SET_CONTROL_LABEL(CONTROL_LABELFILES, items);
430
431   MarkPlaying();
432 }
433
434 bool CGUIWindowMusicPlayList::OnPlayMedia(int iItem)
435 {
436   if (g_partyModeManager.IsEnabled())
437     g_partyModeManager.Play(iItem);
438   else
439   {
440     int iPlaylist=m_guiState->GetPlaylist();
441     if (iPlaylist!=PLAYLIST_NONE)
442     {
443       if (m_guiState.get())
444         m_guiState->SetPlaylistDirectory(m_vecItems.m_strPath);
445
446       g_playlistPlayer.SetCurrentPlaylist( iPlaylist );
447       g_playlistPlayer.Play( iItem );
448     }
449     else
450     {
451       // Reset Playlistplayer, playback started now does
452       // not use the playlistplayer.
453       CFileItem* pItem=m_vecItems[iItem];
454       g_playlistPlayer.Reset();
455       g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
456       g_application.PlayFile(*pItem);
457     }
458   }
459
460   return true;
461 }
462
463 void CGUIWindowMusicPlayList::OnItemLoaded(CFileItem* pItem)
464 {
465   if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->Loaded())
466   { // set label 1+2 from tags
467     if (m_guiState.get()) m_hideExtensions = m_guiState->HideExtensions();
468     CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.nowplayingtrackformat");
469     if (strTrackLeft.IsEmpty())
470       strTrackLeft = g_guiSettings.GetString("musicfiles.trackformat");
471     CStdString strTrackRight=g_guiSettings.GetString("musicfiles.nowplayingtrackformatright");
472     if (strTrackRight.IsEmpty())
473       strTrackRight = g_guiSettings.GetString("musicfiles.trackformatright");
474     CLabelFormatter formatter(strTrackLeft, strTrackRight);
475     formatter.FormatLabels(pItem);
476   } // if (pItem->m_musicInfoTag.Loaded())
477   else
478   {
479     // Our tag may have a duration even if its not loaded
480     if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->GetDuration())
481     {
482       int nDuration = pItem->GetMusicInfoTag()->GetDuration();
483       if (nDuration > 0)
484       {
485         CStdString str;
486         StringUtils::SecondsToTimeString(nDuration, str);
487         pItem->SetLabel2(str);
488       }
489     }
490     else if (pItem->GetLabel() == "") // pls labels come in preformatted
491     {
492       // FIXME: get the position of the item in the playlist
493       //        currently it is hacked into m_iprogramCount
494
495       // No music info and it's not CDDA so we'll just show the filename
496       CStdString str;
497       str = CUtil::GetTitleFromPath(pItem->m_strPath);
498       str.Format("%02.2i. %s ", pItem->m_iprogramCount, str);
499       pItem->SetLabel(str);
500     }
501   }
502
503   if (m_guiState.get())
504   {
505     CPlayList& playlist=g_playlistPlayer.GetPlaylist(m_guiState->GetPlaylist());
506     CPlayList::CPlayListItem& item=playlist[pItem->m_iprogramCount];
507     if (item.m_strPath==pItem->m_strPath &&
508         item.m_lStartOffset==pItem->m_lStartOffset &&
509         item.m_lEndOffset==pItem->m_lEndOffset)
510     {
511       item.SetDescription(pItem->GetLabel());
512     }
513     else
514     { // for some reason the order is wrong - do it the incredibly slow way
515       // FIXME: Highly inefficient. :)
516       // Since we can't directly use the items
517       // of the playlistplayer, we need to set each
518       // label of the playlist items or else the label
519       // is reset to the filename each time Update()
520       // is called and this is annoying. ;)
521       for (int i=0; i<playlist.size(); ++i)
522       {
523         CPlayList::CPlayListItem& item=playlist[i];
524
525         if (item.m_strPath==pItem->m_strPath &&
526             item.m_lStartOffset==pItem->m_lStartOffset &&
527             item.m_lEndOffset==pItem->m_lEndOffset)
528         {
529           item.SetDescription(pItem->GetLabel());
530           break;
531         }
532       }
533     }
534   }
535
536   //  MusicDb items already have thumbs
537   if (!pItem->IsMusicDb())
538   {
539     // Reset thumbs and default icons
540     pItem->SetMusicThumb();
541     pItem->FillInDefaultIcon();
542   }
543 }
544
545 bool CGUIWindowMusicPlayList::Update(const CStdString& strDirectory)
546 {
547   if (m_musicInfoLoader.IsLoading())
548     m_musicInfoLoader.StopThread();
549
550   if (!CGUIWindowMusicBase::Update(strDirectory))
551     return false;
552
553   m_musicInfoLoader.Load(m_vecItems);
554
555
556
557   return true;
558 }
559
560 void CGUIWindowMusicPlayList::GetContextButtons(int itemNumber, CContextButtons &buttons)
561 {
562   // is this playlist playing?
563   bool isPlaying = (g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_MUSIC && g_application.IsPlayingAudio());
564   int itemPlaying = g_playlistPlayer.GetCurrentSong();
565
566   if (itemNumber >= 0 && itemNumber < m_vecItems.Size())
567   {
568     if (m_movingFrom >= 0)
569     {
570       // we can move the item to any position not where we are, and any position not above currently
571       // playing item in party mode
572       if (itemNumber != m_movingFrom && (!g_partyModeManager.IsEnabled() || itemNumber > itemPlaying))
573         buttons.Add(CONTEXT_BUTTON_MOVE_HERE, 13252);         // move item here
574       buttons.Add(CONTEXT_BUTTON_CANCEL_MOVE, 13253);
575     }
576     else
577     { // aren't in a move
578       if (itemNumber > (g_partyModeManager.IsEnabled() ? 1 : 0))
579         buttons.Add(CONTEXT_BUTTON_MOVE_ITEM_UP, 13332);
580       if (itemNumber + 1 < m_vecItems.Size())
581         buttons.Add(CONTEXT_BUTTON_MOVE_ITEM_DOWN, 13333);
582       if (!g_partyModeManager.IsEnabled() || itemNumber != itemPlaying)
583         buttons.Add(CONTEXT_BUTTON_MOVE_ITEM, 13251);
584
585       if (itemNumber != itemPlaying)
586         buttons.Add(CONTEXT_BUTTON_DELETE, 15015);
587     }
588   }
589
590   if (g_partyModeManager.IsEnabled())
591   {
592     buttons.Add(CONTEXT_BUTTON_EDIT_PARTYMODE, 21439);
593     buttons.Add(CONTEXT_BUTTON_CANCEL_PARTYMODE, 588);      // cancel party mode
594   }
595 }
596
597 bool CGUIWindowMusicPlayList::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
598 {
599   switch (button)
600   {
601   case CONTEXT_BUTTON_MOVE_ITEM:
602     m_movingFrom = itemNumber;
603     return true;
604
605   case CONTEXT_BUTTON_MOVE_HERE:
606     MoveItem(m_movingFrom, itemNumber);
607     m_movingFrom = -1;
608     return true;
609
610   case CONTEXT_BUTTON_CANCEL_MOVE:
611     m_movingFrom = -1;
612     return true;
613
614   case CONTEXT_BUTTON_MOVE_ITEM_UP:
615     OnMove(itemNumber, ACTION_MOVE_ITEM_UP);
616     return true;
617
618   case CONTEXT_BUTTON_MOVE_ITEM_DOWN:
619     OnMove(itemNumber, ACTION_MOVE_ITEM_DOWN);
620     return true;
621
622   case CONTEXT_BUTTON_DELETE:
623     RemovePlayListItem(itemNumber);
624     return true;
625     
626   case CONTEXT_BUTTON_CANCEL_PARTYMODE:
627     g_partyModeManager.Disable();
628     return true;
629   case CONTEXT_BUTTON_EDIT_PARTYMODE:
630     CStdString playlist = "P:\\PartyMode.xml";
631     if (CGUIDialogSmartPlaylistEditor::EditPlaylist(playlist))
632     {
633       // apply new rules
634       g_partyModeManager.Disable();
635       g_partyModeManager.Enable();
636     }
637     return true;
638   }
639   return CGUIWindowMusicBase::OnContextButton(itemNumber, button);
640 }
641
642
643 void CGUIWindowMusicPlayList::OnMove(int iItem, int iAction)
644 {
645   if (iItem < 0 || iItem >= m_vecItems.Size()) return;
646
647   bool bRestart = m_musicInfoLoader.IsLoading();
648   if (bRestart)
649     m_musicInfoLoader.StopThread();
650
651   MoveCurrentPlayListItem(iItem, iAction);
652
653   if (bRestart)
654     m_musicInfoLoader.Load(m_vecItems);
655 }
656
657 void CGUIWindowMusicPlayList::MoveItem(int iStart, int iDest)
658 {
659   if (iStart < 0 || iStart >= m_vecItems.Size()) return;
660   if (iDest < 0 || iDest >= m_vecItems.Size()) return;
661
662   // default to move up
663   int iAction = ACTION_MOVE_ITEM_UP;
664   int iDirection = -1;
665   // are we moving down?
666   if (iStart < iDest)
667   {
668     iAction = ACTION_MOVE_ITEM_DOWN;
669     iDirection = 1;
670   }
671
672   bool bRestart = m_musicInfoLoader.IsLoading();
673   if (bRestart)
674     m_musicInfoLoader.StopThread();
675
676   // keep swapping until you get to the destination or you
677   // hit the currently playing song
678   int i = iStart;
679   while (i != iDest)
680   {
681     // try to swap adjacent items
682     if (MoveCurrentPlayListItem(i, iAction, false))
683       i = i + (1 * iDirection);
684     // we hit currently playing song, so abort
685     else
686       break;
687   }
688   Update(m_vecItems.m_strPath);
689
690   if (bRestart)
691     m_musicInfoLoader.Load(m_vecItems);
692 }
693
694 void CGUIWindowMusicPlayList::MarkPlaying()
695 {
696 /*  // clear markings
697   for (int i = 0; i < m_vecItems.Size(); i++)
698     m_vecItems[i]->Select(false);
699
700   // mark the currently playing item
701   if ((g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_MUSIC) && (g_application.IsPlayingAudio()))
702   {
703     int iSong = g_playlistPlayer.GetCurrentSong();
704     if (iSong >= 0 && iSong <= m_vecItems.Size())
705       m_vecItems[iSong]->Select(true);
706   }*/
707 }