1 /* 2 * Copyright 2007, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "MovePLItemsCommand.h" 10 11 #include <new> 12 #include <stdio.h> 13 14 #include <Autolock.h> 15 16 #include "Playlist.h" 17 18 19 using std::nothrow; 20 21 22 MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist, 23 const int32* indices, int32 count, int32 toIndex) 24 : Command() 25 , fPlaylist(playlist) 26 , fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL) 27 , fIndices(count > 0 ? new (nothrow) int32[count] : NULL) 28 , fToIndex(toIndex) 29 , fCount(count) 30 { 31 if (!indices || !fPlaylist || !fRefs || !fIndices) { 32 // indicate a bad object state 33 delete[] fRefs; 34 fRefs = NULL; 35 return; 36 } 37 38 memcpy(fIndices, indices, fCount * sizeof(int32)); 39 40 // init original entry indices and 41 // adjust toIndex compensating for items that 42 // are removed before that index 43 int32 itemsBeforeIndex = 0; 44 for (int32 i = 0; i < fCount; i++) { 45 if (fPlaylist->GetRefAt(fIndices[i], &fRefs[i]) < B_OK) { 46 delete[] fRefs; 47 fRefs = NULL; 48 return; 49 } 50 if (fIndices[i] < fToIndex) 51 itemsBeforeIndex++; 52 } 53 fToIndex -= itemsBeforeIndex; 54 } 55 56 57 MovePLItemsCommand::~MovePLItemsCommand() 58 { 59 delete[] fRefs; 60 delete[] fIndices; 61 } 62 63 64 status_t 65 MovePLItemsCommand::InitCheck() 66 { 67 if (!fPlaylist || !fRefs || !fIndices) 68 return B_NO_INIT; 69 70 // analyse the move, don't return B_OK in case 71 // the container state does not change... 72 73 int32 index = fIndices[0]; 74 // NOTE: fIndices == NULL if fCount < 1 75 76 if (index != fToIndex) { 77 // a change is guaranteed 78 return B_OK; 79 } 80 81 // the insertion index is the same as the index of the first 82 // moved item, a change only occures if the indices of the 83 // moved items is not contiguous 84 bool isContiguous = true; 85 for (int32 i = 1; i < fCount; i++) { 86 if (fIndices[i] != index + 1) { 87 isContiguous = false; 88 break; 89 } 90 index = fIndices[i]; 91 } 92 if (isContiguous) { 93 // the container state will not change because of the move 94 return B_ERROR; 95 } 96 97 return B_OK; 98 } 99 100 101 status_t 102 MovePLItemsCommand::Perform() 103 { 104 BAutolock _(fPlaylist); 105 106 status_t ret = B_OK; 107 108 // remember currently playling ref in case we move it 109 entry_ref currentRef; 110 bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(), 111 ¤tRef) == B_OK; 112 113 // remove refs from playlist 114 for (int32 i = 0; i < fCount; i++) { 115 // "- i" to account for the items already removed 116 fPlaylist->RemoveRef(fIndices[i] - i, false); 117 } 118 119 // add refs to playlist at the insertion index 120 int32 index = fToIndex; 121 for (int32 i = 0; i < fCount; i++) { 122 if (!fPlaylist->AddRef(fRefs[i], index++)) { 123 ret = B_NO_MEMORY; 124 break; 125 } 126 } 127 if (ret < B_OK) 128 return ret; 129 130 // take care about currently played ref 131 if (adjustCurrentRef) 132 fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef)); 133 134 return B_OK; 135 } 136 137 138 status_t 139 MovePLItemsCommand::Undo() 140 { 141 BAutolock _(fPlaylist); 142 143 status_t ret = B_OK; 144 145 // remember currently playling ref in case we move it 146 entry_ref currentRef; 147 bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(), 148 ¤tRef) == B_OK; 149 150 // remove refs from playlist 151 int32 index = fToIndex; 152 for (int32 i = 0; i < fCount; i++) { 153 fPlaylist->RemoveRef(index++, false); 154 } 155 156 // add ref to playlist at remembered indices 157 for (int32 i = 0; i < fCount; i++) { 158 if (!fPlaylist->AddRef(fRefs[i], fIndices[i])) { 159 ret = B_NO_MEMORY; 160 break; 161 } 162 } 163 if (ret < B_OK) 164 return ret; 165 166 // take care about currently played ref 167 if (adjustCurrentRef) 168 fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef)); 169 170 return B_OK; 171 } 172 173 174 void 175 MovePLItemsCommand::GetName(BString& name) 176 { 177 if (fCount > 1) 178 name << "Move Entries"; 179 else 180 name << "Move Entry"; 181 } 182