1/* 2 * Copyright �� 2008-2009 Stephan A��mus <superstippi@gmx.de> 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6#include "RandomizePLItemsCommand.h" 7 8#include <new> 9#include <stdio.h> 10#include <stdlib.h> 11 12#include <Autolock.h> 13#include <Catalog.h> 14#include <Locale.h> 15 16#include "Playlist.h" 17 18 19#undef B_TRANSLATION_CONTEXT 20#define B_TRANSLATION_CONTEXT "MediaPlayer-RandomizePLItemsCmd" 21 22 23using std::nothrow; 24 25 26RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist, 27 BList indices) 28 : 29 PLItemsCommand(), 30 fPlaylist(playlist), 31 fCount(indices.CountItems()), 32 fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL), 33 fListIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL), 34 fRandomInternalIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL) 35{ 36 if (indices.IsEmpty() || !fPlaylist || !fItems || !fListIndices 37 || !fRandomInternalIndices) { 38 // indicate a bad object state 39 delete[] fItems; 40 fItems = NULL; 41 return; 42 } 43 44 memset(fItems, 0, fCount * sizeof(PlaylistItem*)); 45 46 // put the available indices into a "set" 47 BList indexSet; 48 for (int32 i = 0; i < fCount; i++) { 49 fListIndices[i] = (int32)(addr_t)indices.ItemAt(i); 50 fItems[i] = fPlaylist->ItemAt(fListIndices[i]); 51 if (fItems[i] == NULL || !indexSet.AddItem((void*)(addr_t)i)) { 52 // indicate a bad object state 53 delete[] fItems; 54 fItems = NULL; 55 return; 56 } 57 } 58 59 // remove the indices from the set in random order 60 for (int32 i = 0; i < fCount; i++) { 61 int32 randomSetIndex = rand() % indexSet.CountItems(); 62 fRandomInternalIndices[i] = (int32)(addr_t)indexSet.RemoveItem(randomSetIndex); 63 } 64} 65 66 67RandomizePLItemsCommand::~RandomizePLItemsCommand() 68{ 69 delete[] fItems; 70 delete[] fListIndices; 71 delete[] fRandomInternalIndices; 72} 73 74 75status_t 76RandomizePLItemsCommand::InitCheck() 77{ 78 if (!fItems) 79 return B_NO_INIT; 80 81 return B_OK; 82} 83 84 85status_t 86RandomizePLItemsCommand::Perform() 87{ 88 return _Sort(true); 89} 90 91 92status_t 93RandomizePLItemsCommand::Undo() 94{ 95 return _Sort(false); 96} 97 98 99void 100RandomizePLItemsCommand::GetName(BString& name) 101{ 102 name << B_TRANSLATE("Randomize Entries"); 103} 104 105 106status_t 107RandomizePLItemsCommand::_Sort(bool random) 108{ 109 BAutolock _(fPlaylist); 110 111 // remember currently playling item in case we move it 112 PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex()); 113 114 // remove refs from playlist 115 for (int32 i = 0; i < fCount; i++) { 116 // "- i" to account for the items already removed 117 fPlaylist->RemoveItem(fListIndices[i] - i, false); 118 } 119 120 // add refs to playlist at the randomized indices 121 if (random) { 122 for (int32 i = 0; i < fCount; i++) { 123 if (!fPlaylist->AddItem(fItems[fRandomInternalIndices[i]], 124 fListIndices[i])) { 125 return B_NO_MEMORY; 126 } 127 } 128 } else { 129 for (int32 i = 0; i < fCount; i++) { 130 if (!fPlaylist->AddItem(fItems[i], fListIndices[i])) { 131 return B_NO_MEMORY; 132 } 133 } 134 } 135 136 // take care about currently played item 137 if (current != NULL) 138 fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current), false); 139 140 return B_OK; 141} 142