1 /* 2 * Copyright © 2008 Stephan Aßmus. All rights reserved. 3 * 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 14 #include "Playlist.h" 15 16 17 using std::nothrow; 18 19 20 RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist, 21 const int32* indices, int32 count) 22 : Command() 23 , fPlaylist(playlist) 24 , fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL) 25 , fListIndices(count > 0 ? new (nothrow) int32[count] : NULL) 26 , fRandomInternalIndices(count > 0 ? new (nothrow) int32[count] : NULL) 27 , fCount(count) 28 { 29 if (!indices || !fPlaylist || !fRefs || !fListIndices 30 || !fRandomInternalIndices) { 31 // indicate a bad object state 32 delete[] fRefs; 33 fRefs = NULL; 34 return; 35 } 36 37 memcpy(fListIndices, indices, fCount * sizeof(int32)); 38 39 // put the available indices into a "set" 40 BList indexSet; 41 for (int32 i = 0; i < fCount; i++) { 42 if (fPlaylist->GetRefAt(fListIndices[i], &fRefs[i]) < B_OK 43 || !indexSet.AddItem((void*)i)) { 44 // indicate a bad object state 45 delete[] fRefs; 46 fRefs = NULL; 47 return; 48 } 49 } 50 51 // remove the indices from the set in random order 52 for (int32 i = 0; i < fCount; i++) { 53 int32 randomSetIndex = rand() % indexSet.CountItems(); 54 fRandomInternalIndices[i] = (int32)indexSet.RemoveItem(randomSetIndex); 55 } 56 } 57 58 59 RandomizePLItemsCommand::~RandomizePLItemsCommand() 60 { 61 delete[] fRefs; 62 delete[] fListIndices; 63 delete[] fRandomInternalIndices; 64 } 65 66 67 status_t 68 RandomizePLItemsCommand::InitCheck() 69 { 70 if (!fRefs) 71 return B_NO_INIT; 72 73 return B_OK; 74 } 75 76 77 status_t 78 RandomizePLItemsCommand::Perform() 79 { 80 return _Sort(true); 81 } 82 83 84 status_t 85 RandomizePLItemsCommand::Undo() 86 { 87 return _Sort(false); 88 } 89 90 91 void 92 RandomizePLItemsCommand::GetName(BString& name) 93 { 94 name << "Randomize Entries"; 95 } 96 97 98 status_t 99 RandomizePLItemsCommand::_Sort(bool random) 100 { 101 BAutolock _(fPlaylist); 102 103 // remember currently playling ref in case we move it 104 entry_ref currentRef; 105 bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(), 106 ¤tRef) == B_OK; 107 108 // remove refs from playlist 109 for (int32 i = 0; i < fCount; i++) { 110 // "- i" to account for the items already removed 111 fPlaylist->RemoveRef(fListIndices[i] - i, false); 112 } 113 114 // add refs to playlist at the randomized indices 115 if (random) { 116 for (int32 i = 0; i < fCount; i++) { 117 if (!fPlaylist->AddRef(fRefs[fRandomInternalIndices[i]], 118 fListIndices[i])) { 119 return B_NO_MEMORY; 120 } 121 } 122 } else { 123 for (int32 i = 0; i < fCount; i++) { 124 if (!fPlaylist->AddRef(fRefs[i], fListIndices[i])) { 125 return B_NO_MEMORY; 126 } 127 } 128 } 129 130 // take care about currently played ref 131 if (adjustCurrentRef) 132 fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef)); 133 134 return B_OK; 135 } 136