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