* Added "Randomize" feature to Playlist window (Edit menu). It randomizes

either the selected items, or the entire list if nothing is selected.
* Small cleanups here and there.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26264 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2008-07-05 19:21:38 +00:00
parent 0ff21997d1
commit 34ff70da4f
9 changed files with 234 additions and 6 deletions

View File

@ -61,6 +61,7 @@ Application MediaPlayer :
PlaylistListView.cpp PlaylistListView.cpp
PlaylistObserver.cpp PlaylistObserver.cpp
PlaylistWindow.cpp PlaylistWindow.cpp
RandomizePLItemsCommand.cpp
RemovePLItemsCommand.cpp RemovePLItemsCommand.cpp
# settings # settings

View File

@ -28,6 +28,7 @@
#include <Roster.h> #include <Roster.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "EventQueue.h" #include "EventQueue.h"
@ -225,6 +226,8 @@ main()
{ {
EventQueue::CreateDefault(); EventQueue::CreateDefault();
srand(system_time());
gMainApp = new MainApp; gMainApp = new MainApp;
gMainApp->Run(); gMainApp->Run();
delete gMainApp; delete gMainApp;

View File

@ -43,6 +43,7 @@ MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
int32 itemsBeforeIndex = 0; int32 itemsBeforeIndex = 0;
for (int32 i = 0; i < fCount; i++) { for (int32 i = 0; i < fCount; i++) {
if (fPlaylist->GetRefAt(fIndices[i], &fRefs[i]) < B_OK) { if (fPlaylist->GetRefAt(fIndices[i], &fRefs[i]) < B_OK) {
// indicate a bad object state
delete[] fRefs; delete[] fRefs;
fRefs = NULL; fRefs = NULL;
return; return;
@ -64,7 +65,7 @@ MovePLItemsCommand::~MovePLItemsCommand()
status_t status_t
MovePLItemsCommand::InitCheck() MovePLItemsCommand::InitCheck()
{ {
if (!fPlaylist || !fRefs || !fIndices) if (!fRefs)
return B_NO_INIT; return B_NO_INIT;
// analyse the move, don't return B_OK in case // analyse the move, don't return B_OK in case

View File

@ -26,6 +26,7 @@
#include "PlaybackState.h" #include "PlaybackState.h"
#include "Playlist.h" #include "Playlist.h"
#include "PlaylistObserver.h" #include "PlaylistObserver.h"
#include "RandomizePLItemsCommand.h"
#include "RemovePLItemsCommand.h" #include "RemovePLItemsCommand.h"
using std::nothrow; using std::nothrow;
@ -375,6 +376,41 @@ PlaylistListView::RefsReceived(BMessage* message, int32 appendIndex)
} }
void
PlaylistListView::Randomize()
{
int32 count = CountItems();
if (count == 0)
return;
BList indices;
// add current selection
count = 0;
while (true) {
int32 index = CurrentSelection(count);
if (index < 0)
break;
if (!indices.AddItem((void*)index))
return;
count++;
}
// was anything selected?
if (count == 0) {
// no selection, simply add all items
count = CountItems();
for (int32 i = 0; i < count; i++) {
if (!indices.AddItem((void*)i))
return;
}
}
fCommandStack->Perform(new (nothrow) RandomizePLItemsCommand(fPlaylist,
(int32*)indices.Items(), indices.CountItems()));
}
// #pragma mark - // #pragma mark -

View File

@ -44,6 +44,8 @@ class PlaylistListView : public SimpleListView {
void RefsReceived(BMessage* message, void RefsReceived(BMessage* message,
int32 appendIndex); int32 appendIndex);
void Randomize();
private: private:
void _FullSync(); void _FullSync();
void _AddItem(const entry_ref& ref, int32 index); void _AddItem(const entry_ref& ref, int32 index);

View File

@ -31,9 +31,13 @@
#define DEBUG 1 #define DEBUG 1
enum { enum {
// file
M_PLAYLIST_OPEN = 'open', M_PLAYLIST_OPEN = 'open',
M_PLAYLIST_SAVE = 'save', M_PLAYLIST_SAVE = 'save',
M_PLAYLIST_EMPTY = 'emty'
// edit
M_PLAYLIST_EMPTY = 'emty',
M_PLAYLIST_RANDOMIZE = 'rand'
}; };
#define SPACE 5 #define SPACE 5
@ -144,9 +148,14 @@ PlaylistWindow::MessageReceived(BMessage* message)
fOpenPanel = new BFilePanel(B_OPEN_PANEL); fOpenPanel = new BFilePanel(B_OPEN_PANEL);
fOpenPanel->Show(); fOpenPanel->Show();
break; break;
case M_PLAYLIST_EMPTY: case M_PLAYLIST_EMPTY:
fListView->RemoveAll(); fListView->RemoveAll();
break; break;
case M_PLAYLIST_RANDOMIZE:
fListView->Randomize();
break;
default: default:
BWindow::MessageReceived(message); BWindow::MessageReceived(message);
break; break;
@ -180,6 +189,8 @@ PlaylistWindow::_CreateMenu(BRect& frame)
editMenu->AddSeparatorItem(); editMenu->AddSeparatorItem();
editMenu->AddItem(new BMenuItem("Make Empty", editMenu->AddItem(new BMenuItem("Make Empty",
new BMessage(M_PLAYLIST_EMPTY), 'N')); new BMessage(M_PLAYLIST_EMPTY), 'N'));
editMenu->AddItem(new BMenuItem("Randomize",
new BMessage(M_PLAYLIST_RANDOMIZE), 'R'));
menuBar->AddItem(editMenu); menuBar->AddItem(editMenu);
AddChild(menuBar); AddChild(menuBar);

View File

@ -0,0 +1,135 @@
/*
* Copyright © 2008 Stephan Aßmus. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "RandomizePLItemsCommand.h"
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <Autolock.h>
#include "Playlist.h"
using std::nothrow;
RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
const int32* indices, int32 count)
: Command()
, fPlaylist(playlist)
, fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL)
, fListIndices(count > 0 ? new (nothrow) int32[count] : NULL)
, fRandomInternalIndices(count > 0 ? new (nothrow) int32[count] : NULL)
, fCount(count)
{
if (!indices || !fPlaylist || !fRefs || !fListIndices
|| !fRandomInternalIndices) {
// indicate a bad object state
delete[] fRefs;
fRefs = NULL;
return;
}
memcpy(fListIndices, indices, fCount * sizeof(int32));
// put the available indices into a "set"
BList indexSet;
for (int32 i = 0; i < fCount; i++) {
if (fPlaylist->GetRefAt(fListIndices[i], &fRefs[i]) < B_OK
|| !indexSet.AddItem((void*)i)) {
// indicate a bad object state
delete[] fRefs;
fRefs = NULL;
return;
}
}
// remove the indices from the set in random order
for (int32 i = 0; i < fCount; i++) {
int32 randomSetIndex = rand() % indexSet.CountItems();
fRandomInternalIndices[i] = (int32)indexSet.RemoveItem(randomSetIndex);
}
}
RandomizePLItemsCommand::~RandomizePLItemsCommand()
{
delete[] fRefs;
delete[] fListIndices;
delete[] fRandomInternalIndices;
}
status_t
RandomizePLItemsCommand::InitCheck()
{
if (!fRefs)
return B_NO_INIT;
return B_OK;
}
status_t
RandomizePLItemsCommand::Perform()
{
return _Sort(true);
}
status_t
RandomizePLItemsCommand::Undo()
{
return _Sort(false);
}
void
RandomizePLItemsCommand::GetName(BString& name)
{
name << "Randomize Entries";
}
status_t
RandomizePLItemsCommand::_Sort(bool random)
{
BAutolock _(fPlaylist);
// remember currently playling ref in case we move it
entry_ref currentRef;
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
&currentRef) == B_OK;
// remove refs from playlist
for (int32 i = 0; i < fCount; i++) {
// "- i" to account for the items already removed
fPlaylist->RemoveRef(fListIndices[i] - i, false);
}
// add refs to playlist at the randomized indices
if (random) {
for (int32 i = 0; i < fCount; i++) {
if (!fPlaylist->AddRef(fRefs[fRandomInternalIndices[i]],
fListIndices[i])) {
return B_NO_MEMORY;
}
}
} else {
for (int32 i = 0; i < fCount; i++) {
if (!fPlaylist->AddRef(fRefs[i], fListIndices[i])) {
return B_NO_MEMORY;
}
}
}
// take care about currently played ref
if (adjustCurrentRef)
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
return B_OK;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright © 2008 Stephan Aßmus. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef RANDOMIZE_PL_ITEMS_COMMAND_H
#define RANDOMIZE_PL_ITEMS_COMMAND_H
#include "Command.h"
class Playlist;
struct entry_ref;
class RandomizePLItemsCommand : public Command {
public:
RandomizePLItemsCommand(
Playlist* playlist,
const int32* indices,
int32 count);
virtual ~RandomizePLItemsCommand();
virtual status_t InitCheck();
virtual status_t Perform();
virtual status_t Undo();
virtual void GetName(BString& name);
private:
status_t _Sort(bool random);
Playlist* fPlaylist;
entry_ref* fRefs;
int32* fListIndices;
int32* fRandomInternalIndices;
int32 fCount;
};
#endif // RANDOMIZE_PL_ITEMS_COMMAND_H