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 <waddlesplash@gmail.com>
This commit is contained in:
Jaidyn Ann 2020-12-27 19:08:53 -06:00 committed by waddlesplash
parent b966e83785
commit 1cfb79d74a
9 changed files with 50 additions and 41 deletions

View File

@ -22,16 +22,16 @@ using std::nothrow;
CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist,
const int32* indices, int32 count, int32 toIndex)
BList indices, int32 toIndex)
:
PLItemsCommand(),
fPlaylist(playlist),
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
fCount(indices.CountItems()),
fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL),
fToIndex(toIndex),
fCount(count),
fItemsCopied(false)
{
if (!indices || !fPlaylist || !fItems) {
if (indices.IsEmpty() || !fPlaylist || !fItems) {
// indicate a bad object state
delete[] fItems;
fItems = NULL;
@ -42,7 +42,8 @@ CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist,
// init original entries and
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)
fItems[i] = item->Clone();
if (fItems[i] == NULL) {

View File

@ -6,14 +6,16 @@
#define COPY_PL_ITEMS_COMMAND_H
#include <List.h>
#include "PLItemsCommand.h"
class CopyPLItemsCommand : public PLItemsCommand {
public:
CopyPLItemsCommand(
Playlist* playlist,
const int32* indices,
int32 count,
BList indices,
int32 toIndex);
virtual ~CopyPLItemsCommand();
@ -26,9 +28,9 @@ public:
private:
Playlist* fPlaylist;
int32 fCount;
PlaylistItem** fItems;
int32 fToIndex;
int32 fCount;
bool fItemsCopied;
};

View File

@ -23,30 +23,30 @@ using std::nothrow;
MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
const int32* indices, int32 count, int32 toIndex)
BList indices, int32 toIndex)
:
PLItemsCommand(),
fPlaylist(playlist),
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
fIndices(count > 0 ? new (nothrow) int32[count] : NULL),
fToIndex(toIndex),
fCount(count)
fCount(indices.CountItems()),
fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL),
fIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL),
fToIndex(toIndex)
{
if (!indices || !fPlaylist || !fItems || !fIndices) {
if (indices.IsEmpty()) {
// indicate a bad object state
delete[] fItems;
delete fItems;
fItems = NULL;
return;
}
memset(fItems, 0, sizeof(PlaylistItem*) * fCount);
memcpy(fIndices, indices, fCount * sizeof(int32));
// init original entry indices and
// adjust toIndex compensating for items that
// are removed before that index
int32 itemsBeforeIndex = 0;
for (int32 i = 0; i < fCount; i++) {
fIndices[i] = (int32)(addr_t)indices.ItemAt(i);
fItems[i] = fPlaylist->ItemAt(fIndices[i]);
if (fItems[i] == NULL) {
// indicate a bad object state

View File

@ -6,14 +6,16 @@
#define MOVE_PL_ITEMS_COMMAND_H
#include <List.h>
#include "PLItemsCommand.h"
class MovePLItemsCommand : public PLItemsCommand {
public:
MovePLItemsCommand(
Playlist* playlist,
const int32* indices,
int32 count,
BList indices,
int32 toIndex);
virtual ~MovePLItemsCommand();
@ -26,10 +28,10 @@ class MovePLItemsCommand : public PLItemsCommand {
private:
Playlist* fPlaylist;
int32 fCount;
PlaylistItem** fItems;
int32* fIndices;
int32 fToIndex;
int32 fCount;
};
#endif // MOVE_PL_ITEMS_COMMAND_H

View File

@ -483,7 +483,7 @@ void
PlaylistListView::MoveItems(const BList& indices, int32 toIndex)
{
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)
{
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,
(int32*)indices.Items(), indices.CountItems()));
indices));
}
@ -589,7 +589,7 @@ void
PlaylistListView::RemoveItemList(const BList& indices, bool intoTrash)
{
fCommandStack->Perform(new (nothrow) RemovePLItemsCommand(fPlaylist,
(int32*)indices.Items(), indices.CountItems(), intoTrash));
indices, intoTrash));
}

View File

@ -28,12 +28,12 @@ RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
:
PLItemsCommand(),
fPlaylist(playlist),
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
fListIndices(count > 0 ? new (nothrow) int32[count] : NULL),
fRandomInternalIndices(count > 0 ? new (nothrow) int32[count] : NULL),
fCount(count)
fCount(indices.CountItems()),
fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL),
fListIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL),
fRandomInternalIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL)
{
if (!indices || !fPlaylist || !fItems || !fListIndices
if (indices.IsEmpty() || !fPlaylist || !fItems || !fListIndices
|| !fRandomInternalIndices) {
// indicate a bad object state
delete[] fItems;
@ -41,12 +41,12 @@ RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
return;
}
memcpy(fListIndices, indices, fCount * sizeof(int32));
memset(fItems, 0, fCount * sizeof(PlaylistItem*));
// put the available indices into a "set"
BList indexSet;
for (int32 i = 0; i < fCount; i++) {
fIndices[i] = (int32)(addr_t)indices.ItemAt(i);
fItems[i] = fPlaylist->ItemAt(fListIndices[i]);
if (fItems[i] == NULL || !indexSet.AddItem((void*)(addr_t)i)) {
// indicate a bad object state

View File

@ -6,14 +6,16 @@
#define RANDOMIZE_PL_ITEMS_COMMAND_H
#include <List.h>
#include "PLItemsCommand.h"
class RandomizePLItemsCommand : public PLItemsCommand {
public:
RandomizePLItemsCommand(
Playlist* playlist,
const int32* indices,
int32 count);
BList indices);
virtual ~RandomizePLItemsCommand();
virtual status_t InitCheck();
@ -27,10 +29,10 @@ private:
status_t _Sort(bool random);
Playlist* fPlaylist;
int32 fCount;
PlaylistItem** fItems;
int32* fListIndices;
int32* fRandomInternalIndices;
int32 fCount;
};
#endif // RANDOMIZE_PL_ITEMS_COMMAND_H

View File

@ -24,29 +24,29 @@ using std::nothrow;
RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist,
const int32* indices, int32 count, bool moveFilesToTrash)
BList indices, bool moveFilesToTrash)
:
PLItemsCommand(),
fPlaylist(playlist),
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
fIndices(count > 0 ? new (nothrow) int32[count] : NULL),
fCount(count),
fCount(indices.CountItems()),
fItems(fCount > 0 ? new (nothrow) PlaylistItem*[fCount] : NULL),
fIndices(fCount > 0 ? new (nothrow) int32[fCount] : NULL),
fMoveFilesToTrash(moveFilesToTrash),
fMoveErrorShown(false),
fItemsRemoved(false)
{
if (!indices || !fPlaylist || !fItems || !fIndices) {
if (indices.IsEmpty()) {
// indicate a bad object state
delete[] fItems;
fItems = NULL;
return;
}
memcpy(fIndices, indices, fCount * sizeof(int32));
memset(fItems, 0, fCount * sizeof(PlaylistItem*));
// init original entry indices
for (int32 i = 0; i < fCount; i++) {
fIndices[i] = (int32)(addr_t)indices.ItemAt(i);
fItems[i] = fPlaylist->ItemAt(fIndices[i]);
if (fItems[i] == NULL) {
delete[] fItems;

View File

@ -6,14 +6,16 @@
#define REMOVE_PL_ITEMS_COMMAND_H
#include <List.h>
#include "PLItemsCommand.h"
class RemovePLItemsCommand : public PLItemsCommand {
public:
RemovePLItemsCommand(
Playlist* playlist,
const int32* indices,
int32 count,
BList indices,
bool moveFilesToTrash = false);
virtual ~RemovePLItemsCommand();
@ -26,9 +28,9 @@ public:
private:
Playlist* fPlaylist;
int32 fCount;
PlaylistItem** fItems;
int32* fIndices;
int32 fCount;
bool fMoveFilesToTrash;
bool fMoveErrorShown;
bool fItemsRemoved;