MediaPlayer: Fix playlist manipulation on x86_64

Fixes a problem on x86_64 with removing, shuffling, and moving
multiple playlist items.

Instead of casting directly between an array of addr_t and int32
values, an int32 array is filled manually. Commands are passed
BLists instead of int32 arrays.

Fixes #15737 #16698

Change-Id: I5f67cd511ba10b16bd52d87cda380dd15ce7ee67
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3553
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Jaidyn Ann
2020-12-29 19:20:36 +00:00
committed by waddlesplash
parent b966e83785
commit 1cfb79d74a
9 changed files with 50 additions and 41 deletions
@@ -22,16 +22,16 @@ using std::nothrow;
CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist, CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist,
const int32* indices, int32 count, int32 toIndex) BList indices, int32 toIndex)
: :
PLItemsCommand(), PLItemsCommand(),
fPlaylist(playlist), fPlaylist(playlist),
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL), fCount(indices.CountItems()),
fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL),
fToIndex(toIndex), fToIndex(toIndex),
fCount(count),
fItemsCopied(false) fItemsCopied(false)
{ {
if (!indices || !fPlaylist || !fItems) { if (indices.IsEmpty() || !fPlaylist || !fItems) {
// indicate a bad object state // indicate a bad object state
delete[] fItems; delete[] fItems;
fItems = NULL; fItems = NULL;
@@ -42,7 +42,8 @@ CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist,
// init original entries and // init original entries and
for (int32 i = 0; i < fCount; i++) { for (int32 i = 0; i < fCount; i++) {
PlaylistItem* item = fPlaylist->ItemAt(indices[i]); PlaylistItem* item =
fPlaylist->ItemAt((int32)(addr_t)indices.ItemAt(i));
if (item != NULL) if (item != NULL)
fItems[i] = item->Clone(); fItems[i] = item->Clone();
if (fItems[i] == NULL) { if (fItems[i] == NULL) {
@@ -6,14 +6,16 @@
#define COPY_PL_ITEMS_COMMAND_H #define COPY_PL_ITEMS_COMMAND_H
#include <List.h>
#include "PLItemsCommand.h" #include "PLItemsCommand.h"
class CopyPLItemsCommand : public PLItemsCommand { class CopyPLItemsCommand : public PLItemsCommand {
public: public:
CopyPLItemsCommand( CopyPLItemsCommand(
Playlist* playlist, Playlist* playlist,
const int32* indices, BList indices,
int32 count,
int32 toIndex); int32 toIndex);
virtual ~CopyPLItemsCommand(); virtual ~CopyPLItemsCommand();
@@ -26,9 +28,9 @@ public:
private: private:
Playlist* fPlaylist; Playlist* fPlaylist;
int32 fCount;
PlaylistItem** fItems; PlaylistItem** fItems;
int32 fToIndex; int32 fToIndex;
int32 fCount;
bool fItemsCopied; bool fItemsCopied;
}; };
@@ -23,30 +23,30 @@ using std::nothrow;
MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist, MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
const int32* indices, int32 count, int32 toIndex) BList indices, int32 toIndex)
: :
PLItemsCommand(), PLItemsCommand(),
fPlaylist(playlist), fPlaylist(playlist),
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL), fCount(indices.CountItems()),
fIndices(count > 0 ? new (nothrow) int32[count] : NULL), fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL),
fToIndex(toIndex), fIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL),
fCount(count) fToIndex(toIndex)
{ {
if (!indices || !fPlaylist || !fItems || !fIndices) { if (indices.IsEmpty()) {
// indicate a bad object state // indicate a bad object state
delete[] fItems; delete fItems;
fItems = NULL; fItems = NULL;
return; return;
} }
memset(fItems, 0, sizeof(PlaylistItem*) * fCount); memset(fItems, 0, sizeof(PlaylistItem*) * fCount);
memcpy(fIndices, indices, fCount * sizeof(int32));
// init original entry indices and // init original entry indices and
// adjust toIndex compensating for items that // adjust toIndex compensating for items that
// are removed before that index // are removed before that index
int32 itemsBeforeIndex = 0; int32 itemsBeforeIndex = 0;
for (int32 i = 0; i < fCount; i++) { for (int32 i = 0; i < fCount; i++) {
fIndices[i] = (int32)(addr_t)indices.ItemAt(i);
fItems[i] = fPlaylist->ItemAt(fIndices[i]); fItems[i] = fPlaylist->ItemAt(fIndices[i]);
if (fItems[i] == NULL) { if (fItems[i] == NULL) {
// indicate a bad object state // indicate a bad object state
@@ -6,14 +6,16 @@
#define MOVE_PL_ITEMS_COMMAND_H #define MOVE_PL_ITEMS_COMMAND_H
#include <List.h>
#include "PLItemsCommand.h" #include "PLItemsCommand.h"
class MovePLItemsCommand : public PLItemsCommand { class MovePLItemsCommand : public PLItemsCommand {
public: public:
MovePLItemsCommand( MovePLItemsCommand(
Playlist* playlist, Playlist* playlist,
const int32* indices, BList indices,
int32 count,
int32 toIndex); int32 toIndex);
virtual ~MovePLItemsCommand(); virtual ~MovePLItemsCommand();
@@ -26,10 +28,10 @@ class MovePLItemsCommand : public PLItemsCommand {
private: private:
Playlist* fPlaylist; Playlist* fPlaylist;
int32 fCount;
PlaylistItem** fItems; PlaylistItem** fItems;
int32* fIndices; int32* fIndices;
int32 fToIndex; int32 fToIndex;
int32 fCount;
}; };
#endif // MOVE_PL_ITEMS_COMMAND_H #endif // MOVE_PL_ITEMS_COMMAND_H
@@ -483,7 +483,7 @@ void
PlaylistListView::MoveItems(const BList& indices, int32 toIndex) PlaylistListView::MoveItems(const BList& indices, int32 toIndex)
{ {
fCommandStack->Perform(new (nothrow) MovePLItemsCommand(fPlaylist, fCommandStack->Perform(new (nothrow) MovePLItemsCommand(fPlaylist,
(int32*)indices.Items(), indices.CountItems(), toIndex)); indices, toIndex));
} }
@@ -491,7 +491,7 @@ void
PlaylistListView::CopyItems(const BList& indices, int32 toIndex) PlaylistListView::CopyItems(const BList& indices, int32 toIndex)
{ {
fCommandStack->Perform(new (nothrow) CopyPLItemsCommand(fPlaylist, fCommandStack->Perform(new (nothrow) CopyPLItemsCommand(fPlaylist,
(int32*)indices.Items(), indices.CountItems(), toIndex)); indices, toIndex));
} }
@@ -563,7 +563,7 @@ PlaylistListView::Randomize()
} }
fCommandStack->Perform(new (nothrow) RandomizePLItemsCommand(fPlaylist, fCommandStack->Perform(new (nothrow) RandomizePLItemsCommand(fPlaylist,
(int32*)indices.Items(), indices.CountItems())); indices));
} }
@@ -589,7 +589,7 @@ void
PlaylistListView::RemoveItemList(const BList& indices, bool intoTrash) PlaylistListView::RemoveItemList(const BList& indices, bool intoTrash)
{ {
fCommandStack->Perform(new (nothrow) RemovePLItemsCommand(fPlaylist, fCommandStack->Perform(new (nothrow) RemovePLItemsCommand(fPlaylist,
(int32*)indices.Items(), indices.CountItems(), intoTrash)); indices, intoTrash));
} }
@@ -28,12 +28,12 @@ RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
: :
PLItemsCommand(), PLItemsCommand(),
fPlaylist(playlist), fPlaylist(playlist),
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL), fCount(indices.CountItems()),
fListIndices(count > 0 ? new (nothrow) int32[count] : NULL), fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL),
fRandomInternalIndices(count > 0 ? new (nothrow) int32[count] : NULL), fListIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL),
fCount(count) fRandomInternalIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL)
{ {
if (!indices || !fPlaylist || !fItems || !fListIndices if (indices.IsEmpty() || !fPlaylist || !fItems || !fListIndices
|| !fRandomInternalIndices) { || !fRandomInternalIndices) {
// indicate a bad object state // indicate a bad object state
delete[] fItems; delete[] fItems;
@@ -41,12 +41,12 @@ RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
return; return;
} }
memcpy(fListIndices, indices, fCount * sizeof(int32));
memset(fItems, 0, fCount * sizeof(PlaylistItem*)); memset(fItems, 0, fCount * sizeof(PlaylistItem*));
// put the available indices into a "set" // put the available indices into a "set"
BList indexSet; BList indexSet;
for (int32 i = 0; i < fCount; i++) { for (int32 i = 0; i < fCount; i++) {
fIndices[i] = (int32)(addr_t)indices.ItemAt(i);
fItems[i] = fPlaylist->ItemAt(fListIndices[i]); fItems[i] = fPlaylist->ItemAt(fListIndices[i]);
if (fItems[i] == NULL || !indexSet.AddItem((void*)(addr_t)i)) { if (fItems[i] == NULL || !indexSet.AddItem((void*)(addr_t)i)) {
// indicate a bad object state // indicate a bad object state
@@ -6,14 +6,16 @@
#define RANDOMIZE_PL_ITEMS_COMMAND_H #define RANDOMIZE_PL_ITEMS_COMMAND_H
#include <List.h>
#include "PLItemsCommand.h" #include "PLItemsCommand.h"
class RandomizePLItemsCommand : public PLItemsCommand { class RandomizePLItemsCommand : public PLItemsCommand {
public: public:
RandomizePLItemsCommand( RandomizePLItemsCommand(
Playlist* playlist, Playlist* playlist,
const int32* indices, BList indices);
int32 count);
virtual ~RandomizePLItemsCommand(); virtual ~RandomizePLItemsCommand();
virtual status_t InitCheck(); virtual status_t InitCheck();
@@ -27,10 +29,10 @@ private:
status_t _Sort(bool random); status_t _Sort(bool random);
Playlist* fPlaylist; Playlist* fPlaylist;
int32 fCount;
PlaylistItem** fItems; PlaylistItem** fItems;
int32* fListIndices; int32* fListIndices;
int32* fRandomInternalIndices; int32* fRandomInternalIndices;
int32 fCount;
}; };
#endif // RANDOMIZE_PL_ITEMS_COMMAND_H #endif // RANDOMIZE_PL_ITEMS_COMMAND_H
@@ -24,29 +24,29 @@ using std::nothrow;
RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist, RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist,
const int32* indices, int32 count, bool moveFilesToTrash) BList indices, bool moveFilesToTrash)
: :
PLItemsCommand(), PLItemsCommand(),
fPlaylist(playlist), fPlaylist(playlist),
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL), fCount(indices.CountItems()),
fIndices(count > 0 ? new (nothrow) int32[count] : NULL), fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL),
fCount(count), fIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL),
fMoveFilesToTrash(moveFilesToTrash), fMoveFilesToTrash(moveFilesToTrash),
fMoveErrorShown(false), fMoveErrorShown(false),
fItemsRemoved(false) fItemsRemoved(false)
{ {
if (!indices || !fPlaylist || !fItems || !fIndices) { if (indices.IsEmpty()) {
// indicate a bad object state // indicate a bad object state
delete[] fItems; delete[] fItems;
fItems = NULL; fItems = NULL;
return; return;
} }
memcpy(fIndices, indices, fCount * sizeof(int32));
memset(fItems, 0, fCount * sizeof(PlaylistItem*)); memset(fItems, 0, fCount * sizeof(PlaylistItem*));
// init original entry indices // init original entry indices
for (int32 i = 0; i < fCount; i++) { for (int32 i = 0; i < fCount; i++) {
fIndices[i] = (int32)(addr_t)indices.ItemAt(i);
fItems[i] = fPlaylist->ItemAt(fIndices[i]); fItems[i] = fPlaylist->ItemAt(fIndices[i]);
if (fItems[i] == NULL) { if (fItems[i] == NULL) {
delete[] fItems; delete[] fItems;
@@ -6,14 +6,16 @@
#define REMOVE_PL_ITEMS_COMMAND_H #define REMOVE_PL_ITEMS_COMMAND_H
#include <List.h>
#include "PLItemsCommand.h" #include "PLItemsCommand.h"
class RemovePLItemsCommand : public PLItemsCommand { class RemovePLItemsCommand : public PLItemsCommand {
public: public:
RemovePLItemsCommand( RemovePLItemsCommand(
Playlist* playlist, Playlist* playlist,
const int32* indices, BList indices,
int32 count,
bool moveFilesToTrash = false); bool moveFilesToTrash = false);
virtual ~RemovePLItemsCommand(); virtual ~RemovePLItemsCommand();
@@ -26,9 +28,9 @@ public:
private: private:
Playlist* fPlaylist; Playlist* fPlaylist;
int32 fCount;
PlaylistItem** fItems; PlaylistItem** fItems;
int32* fIndices; int32* fIndices;
int32 fCount;
bool fMoveFilesToTrash; bool fMoveFilesToTrash;
bool fMoveErrorShown; bool fMoveErrorShown;
bool fItemsRemoved; bool fItemsRemoved;