* Changed the PlaylistItem interface to be hopefully more flexible. It can
probably still be improved. * Renamed EntryRefPlaylistItem to just FilePlaylistItem. * Moved the "move into Trash" and "restore from Trash" implementation into FilePlaylistItem. Also added what's needed to allow Tracker to restore the entry itself. * Refactored everything to make Playlist use PlaylistItems instead of entry_refs and all that entails... * The transition to virtualize PlaylistItems is not complete yet in the Controller, since it still uses BMediaFile there. But it's much easier to change that now. * Objects which keep a PlaylistItem around do correct reference counting, but some commands could be simplified if they were using references as well. It still should work correctly, though, if I didn't miss anything. It should also fix theoretical situations of encountering out-of-memory while messing with the Playlist leading to inconsistent state between Undo/Redo and then leaking items because of that. * Added the discussed change that MediaPlayer checks it's own supported types before rejecting a file by super type. (untested) * When importing playlist items, the currently playling item is better maintained during Undo/Redo. * Some debugging code added in MediaTrackAudioSupplier, no functional changes. * Fixed a number of coding style issues and automatic whitespace cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30834 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -91,7 +91,7 @@ Controller::Controller()
|
|||||||
// but use only if there are multiple players running at all!
|
// but use only if there are multiple players running at all!
|
||||||
fMuted(false),
|
fMuted(false),
|
||||||
|
|
||||||
fRef(),
|
fItem(NULL),
|
||||||
fMediaFile(NULL),
|
fMediaFile(NULL),
|
||||||
|
|
||||||
fVideoSupplier(new ProxyVideoSupplier()),
|
fVideoSupplier(new ProxyVideoSupplier()),
|
||||||
@@ -185,11 +185,11 @@ Controller::CreateAudioSupplier()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Controller::SetTo(const entry_ref &ref)
|
Controller::SetTo(const PlaylistItemRef& item)
|
||||||
{
|
{
|
||||||
BAutolock _(this);
|
BAutolock _(this);
|
||||||
|
|
||||||
if (fRef == ref) {
|
if (fItem == item) {
|
||||||
if (InitCheck() == B_OK) {
|
if (InitCheck() == B_OK) {
|
||||||
if (fAutoplay) {
|
if (fAutoplay) {
|
||||||
SetPosition(0.0);
|
SetPosition(0.0);
|
||||||
@@ -199,7 +199,7 @@ Controller::SetTo(const entry_ref &ref)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
fRef = ref;
|
fItem = item;
|
||||||
|
|
||||||
fAudioSupplier->SetSupplier(NULL, fVideoFrameRate);
|
fAudioSupplier->SetSupplier(NULL, fVideoFrameRate);
|
||||||
fVideoSupplier->SetSupplier(NULL);
|
fVideoSupplier->SetSupplier(NULL);
|
||||||
@@ -224,12 +224,13 @@ Controller::SetTo(const entry_ref &ref)
|
|||||||
fDuration = 0;
|
fDuration = 0;
|
||||||
fVideoFrameRate = 25.0;
|
fVideoFrameRate = 25.0;
|
||||||
|
|
||||||
status_t err;
|
if (fItem.Get() == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
BMediaFile* mf = new BMediaFile(&ref);
|
BMediaFile* mf = fItem->CreateMediaFile();
|
||||||
ObjectDeleter<BMediaFile> mediaFileDeleter(mf);
|
ObjectDeleter<BMediaFile> mediaFileDeleter(mf);
|
||||||
|
|
||||||
err = mf->InitCheck();
|
status_t err = mf->InitCheck();
|
||||||
if (err != B_OK) {
|
if (err != B_OK) {
|
||||||
printf("Controller::SetTo: initcheck failed\n");
|
printf("Controller::SetTo: initcheck failed\n");
|
||||||
_NotifyFileChanged();
|
_NotifyFileChanged();
|
||||||
@@ -679,14 +680,9 @@ status_t
|
|||||||
Controller::GetLocation(BString* location)
|
Controller::GetLocation(BString* location)
|
||||||
{
|
{
|
||||||
// you need to hold the data lock
|
// you need to hold the data lock
|
||||||
if (!fMediaFile)
|
if (fItem.Get() == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
BPath path(&fRef);
|
*location = fItem->LocationURI();
|
||||||
status_t ret = path.InitCheck();
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
*location = "";
|
|
||||||
*location << "file://" << path.Path();
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -695,9 +691,9 @@ status_t
|
|||||||
Controller::GetName(BString* name)
|
Controller::GetName(BString* name)
|
||||||
{
|
{
|
||||||
// you need to hold the data lock
|
// you need to hold the data lock
|
||||||
if (!fMediaFile)
|
if (fItem.Get() == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
*name = fRef.name;
|
*name = fItem->Name();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,11 +31,13 @@
|
|||||||
|
|
||||||
#include "ListenerAdapter.h"
|
#include "ListenerAdapter.h"
|
||||||
#include "NodeManager.h"
|
#include "NodeManager.h"
|
||||||
|
#include "PlaylistItem.h"
|
||||||
|
|
||||||
class AudioTrackSupplier;
|
class AudioTrackSupplier;
|
||||||
class BBitmap;
|
class BBitmap;
|
||||||
class BMediaFile;
|
class BMediaFile;
|
||||||
class BMediaTrack;
|
class BMediaTrack;
|
||||||
|
class PlaylistItem;
|
||||||
class ProxyAudioSupplier;
|
class ProxyAudioSupplier;
|
||||||
class ProxyVideoSupplier;
|
class ProxyVideoSupplier;
|
||||||
class SoundOutput;
|
class SoundOutput;
|
||||||
@@ -78,9 +80,9 @@ public:
|
|||||||
virtual AudioSupplier* CreateAudioSupplier();
|
virtual AudioSupplier* CreateAudioSupplier();
|
||||||
|
|
||||||
// Controller
|
// Controller
|
||||||
status_t SetTo(const entry_ref &ref);
|
status_t SetTo(const PlaylistItemRef& item);
|
||||||
entry_ref Ref() const
|
const PlaylistItem* Item() const
|
||||||
{ return fRef; }
|
{ return fItem.Get(); }
|
||||||
void PlayerActivated(bool active);
|
void PlayerActivated(bool active);
|
||||||
|
|
||||||
void GetSize(int *width, int *height);
|
void GetSize(int *width, int *height);
|
||||||
@@ -167,7 +169,7 @@ private:
|
|||||||
float fActiveVolume;
|
float fActiveVolume;
|
||||||
bool fMuted;
|
bool fMuted;
|
||||||
|
|
||||||
entry_ref fRef;
|
PlaylistItemRef fItem;
|
||||||
BMediaFile* fMediaFile;
|
BMediaFile* fMediaFile;
|
||||||
|
|
||||||
ProxyVideoSupplier* fVideoSupplier;
|
ProxyVideoSupplier* fVideoSupplier;
|
||||||
|
|||||||
@@ -63,18 +63,18 @@ ControllerView::Draw(BRect updateRect)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ControllerView::MessageReceived(BMessage *msg)
|
ControllerView::MessageReceived(BMessage* message)
|
||||||
{
|
{
|
||||||
switch (msg->what) {
|
switch (message->what) {
|
||||||
case MSG_PLAYLIST_REF_ADDED:
|
case MSG_PLAYLIST_ITEM_ADDED:
|
||||||
case MSG_PLAYLIST_REF_REMOVED:
|
case MSG_PLAYLIST_ITEM_REMOVED:
|
||||||
case MSG_PLAYLIST_REFS_SORTED:
|
case MSG_PLAYLIST_ITEMS_SORTED:
|
||||||
case MSG_PLAYLIST_CURRENT_REF_CHANGED:
|
case MSG_PLAYLIST_CURRENT_ITEM_CHANGED:
|
||||||
_CheckSkippable();
|
_CheckSkippable();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TransportControlGroup::MessageReceived(msg);
|
TransportControlGroup::MessageReceived(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ void
|
|||||||
ControllerView::SkipBackward()
|
ControllerView::SkipBackward()
|
||||||
{
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() - 1);
|
fPlaylist->SetCurrentItemIndex(fPlaylist->CurrentItemIndex() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ void
|
|||||||
ControllerView::SkipForward()
|
ControllerView::SkipForward()
|
||||||
{
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1);
|
fPlaylist->SetCurrentItemIndex(fPlaylist->CurrentItemIndex() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include "Controller.h"
|
#include "Controller.h"
|
||||||
#include "ControllerObserver.h"
|
#include "ControllerObserver.h"
|
||||||
|
#include "PlaylistItem.h"
|
||||||
|
|
||||||
|
|
||||||
#define NAME "File Info"
|
#define NAME "File Info"
|
||||||
@@ -55,7 +56,7 @@ public:
|
|||||||
virtual ~InfoView();
|
virtual ~InfoView();
|
||||||
virtual void Draw(BRect updateRect);
|
virtual void Draw(BRect updateRect);
|
||||||
|
|
||||||
status_t SetIcon(const entry_ref& ref);
|
status_t SetIcon(const PlaylistItem* item);
|
||||||
status_t SetIcon(const char* mimeType);
|
status_t SetIcon(const char* mimeType);
|
||||||
void SetGenericIcon();
|
void SetGenericIcon();
|
||||||
|
|
||||||
@@ -106,11 +107,9 @@ InfoView::Draw(BRect updateRect)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
InfoView::SetIcon(const entry_ref& ref)
|
InfoView::SetIcon(const PlaylistItem* item)
|
||||||
{
|
{
|
||||||
BNode node(&ref);
|
return item->GetIcon(fIconBitmap, B_LARGE_ICON);
|
||||||
BNodeInfo info(&node);
|
|
||||||
return info.GetTrackerIcon(fIconBitmap, B_LARGE_ICON);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -441,8 +440,8 @@ printf("InfoWin::Update(0x%08lx)\n", which);
|
|||||||
if (which & INFO_FILE) {
|
if (which & INFO_FILE) {
|
||||||
bool iconSet = false;
|
bool iconSet = false;
|
||||||
if (fController->HasFile()) {
|
if (fController->HasFile()) {
|
||||||
entry_ref ref = fController->Ref();
|
const PlaylistItem* item = fController->Item();
|
||||||
iconSet = fInfoView->SetIcon(ref) == B_OK;
|
iconSet = fInfoView->SetIcon(item) == B_OK;
|
||||||
media_file_format fileFormat;
|
media_file_format fileFormat;
|
||||||
BString s;
|
BString s;
|
||||||
if (fController->GetFileFormatInfo(&fileFormat) == B_OK) {
|
if (fController->GetFileFormatInfo(&fileFormat) == B_OK) {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ Application MediaPlayer :
|
|||||||
|
|
||||||
# playlist
|
# playlist
|
||||||
CopyPLItemsCommand.cpp
|
CopyPLItemsCommand.cpp
|
||||||
EntryRefPlaylistItem.cpp
|
FilePlaylistItem.cpp
|
||||||
ImportPLItemsCommand.cpp
|
ImportPLItemsCommand.cpp
|
||||||
ListViews.cpp
|
ListViews.cpp
|
||||||
MovePLItemsCommand.cpp
|
MovePLItemsCommand.cpp
|
||||||
@@ -64,6 +64,7 @@ Application MediaPlayer :
|
|||||||
PlaylistListView.cpp
|
PlaylistListView.cpp
|
||||||
PlaylistObserver.cpp
|
PlaylistObserver.cpp
|
||||||
PlaylistWindow.cpp
|
PlaylistWindow.cpp
|
||||||
|
PLItemsCommand.cpp
|
||||||
RandomizePLItemsCommand.cpp
|
RandomizePLItemsCommand.cpp
|
||||||
RemovePLItemsCommand.cpp
|
RemovePLItemsCommand.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* MainWin.cpp - Media Player for the Haiku Operating System
|
* MainWin.cpp - Media Player for the Haiku Operating System
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Marcus Overhagen <[email protected]>
|
* Copyright (C) 2006 Marcus Overhagen <[email protected]>
|
||||||
* Copyright (C) 2007-2008 Stephan Aßmus <[email protected]> (GPL->MIT ok)
|
* Copyright (C) 2007-2009 Stephan Aßmus <[email protected]> (GPL->MIT ok)
|
||||||
* Copyright (C) 2007-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok)
|
* Copyright (C) 2007-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
* USA.
|
* USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MainWin.h"
|
#include "MainWin.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
#include "ControllerObserver.h"
|
#include "ControllerObserver.h"
|
||||||
#include "MainApp.h"
|
#include "MainApp.h"
|
||||||
#include "PeakView.h"
|
#include "PeakView.h"
|
||||||
|
#include "PlaylistItem.h"
|
||||||
#include "PlaylistObserver.h"
|
#include "PlaylistObserver.h"
|
||||||
#include "PlaylistWindow.h"
|
#include "PlaylistWindow.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
@@ -379,33 +381,35 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// PlaylistObserver messages
|
// PlaylistObserver messages
|
||||||
case MSG_PLAYLIST_REF_ADDED: {
|
case MSG_PLAYLIST_ITEM_ADDED:
|
||||||
entry_ref ref;
|
{
|
||||||
|
PlaylistItem* item;
|
||||||
int32 index;
|
int32 index;
|
||||||
if (msg->FindRef("refs", &ref) == B_OK
|
if (msg->FindPointer("item", (void**)&item) == B_OK
|
||||||
&& msg->FindInt32("index", &index) == B_OK) {
|
&& msg->FindInt32("index", &index) == B_OK) {
|
||||||
_AddPlaylistItem(ref, index);
|
_AddPlaylistItem(item, index);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_PLAYLIST_REF_REMOVED: {
|
case MSG_PLAYLIST_ITEM_REMOVED:
|
||||||
|
{
|
||||||
int32 index;
|
int32 index;
|
||||||
if (msg->FindInt32("index", &index) == B_OK) {
|
if (msg->FindInt32("index", &index) == B_OK)
|
||||||
_RemovePlaylistItem(index);
|
_RemovePlaylistItem(index);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_PLAYLIST_CURRENT_REF_CHANGED: {
|
case MSG_PLAYLIST_CURRENT_ITEM_CHANGED:
|
||||||
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
int32 index;
|
int32 index;
|
||||||
if (msg->FindInt32("index", &index) < B_OK
|
if (msg->FindInt32("index", &index) < B_OK
|
||||||
|| index != fPlaylist->CurrentRefIndex())
|
|| index != fPlaylist->CurrentItemIndex())
|
||||||
break;
|
break;
|
||||||
entry_ref ref;
|
PlaylistItemRef item(fPlaylist->ItemAt(index));
|
||||||
if (fPlaylist->GetRefAt(index, &ref) == B_OK) {
|
if (item.Get() != NULL) {
|
||||||
printf("open ref: %s\n", ref.name);
|
printf("open playlist item: %s\n", item->Name().String());
|
||||||
OpenFile(ref);
|
OpenPlaylistItem(item);
|
||||||
_MarkPlaylistItem(index);
|
_MarkPlaylistItem(index);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -416,8 +420,8 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
{
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
bool hadNext = fPlaylist->SetCurrentRefIndex(
|
bool hadNext = fPlaylist->SetCurrentItemIndex(
|
||||||
fPlaylist->CurrentRefIndex() + 1);
|
fPlaylist->CurrentItemIndex() + 1);
|
||||||
if (!hadNext) {
|
if (!hadNext) {
|
||||||
if (fHasVideo) {
|
if (fHasVideo) {
|
||||||
if (fCloseWhenDonePlayingMovie)
|
if (fCloseWhenDonePlayingMovie)
|
||||||
@@ -434,7 +438,8 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
// notification
|
// notification
|
||||||
// _UpdatePlaylistMenu();
|
// _UpdatePlaylistMenu();
|
||||||
break;
|
break;
|
||||||
case MSG_CONTROLLER_VIDEO_TRACK_CHANGED: {
|
case MSG_CONTROLLER_VIDEO_TRACK_CHANGED:
|
||||||
|
{
|
||||||
int32 index;
|
int32 index;
|
||||||
if (msg->FindInt32("index", &index) == B_OK) {
|
if (msg->FindInt32("index", &index) == B_OK) {
|
||||||
BMenuItem* item = fVideoTrackMenu->ItemAt(index);
|
BMenuItem* item = fVideoTrackMenu->ItemAt(index);
|
||||||
@@ -443,7 +448,8 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_CONTROLLER_AUDIO_TRACK_CHANGED: {
|
case MSG_CONTROLLER_AUDIO_TRACK_CHANGED:
|
||||||
|
{
|
||||||
int32 index;
|
int32 index;
|
||||||
if (msg->FindInt32("index", &index) == B_OK) {
|
if (msg->FindInt32("index", &index) == B_OK) {
|
||||||
BMenuItem* item = fAudioTrackMenu->ItemAt(index);
|
BMenuItem* item = fAudioTrackMenu->ItemAt(index);
|
||||||
@@ -452,25 +458,29 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED: {
|
case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED:
|
||||||
|
{
|
||||||
uint32 state;
|
uint32 state;
|
||||||
if (msg->FindInt32("state", (int32*)&state) == B_OK)
|
if (msg->FindInt32("state", (int32*)&state) == B_OK)
|
||||||
fControls->SetPlaybackState(state);
|
fControls->SetPlaybackState(state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_CONTROLLER_POSITION_CHANGED: {
|
case MSG_CONTROLLER_POSITION_CHANGED:
|
||||||
|
{
|
||||||
float position;
|
float position;
|
||||||
if (msg->FindFloat("position", &position) == B_OK)
|
if (msg->FindFloat("position", &position) == B_OK)
|
||||||
fControls->SetPosition(position);
|
fControls->SetPosition(position);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_CONTROLLER_VOLUME_CHANGED: {
|
case MSG_CONTROLLER_VOLUME_CHANGED:
|
||||||
|
{
|
||||||
float volume;
|
float volume;
|
||||||
if (msg->FindFloat("volume", &volume) == B_OK)
|
if (msg->FindFloat("volume", &volume) == B_OK)
|
||||||
fControls->SetVolume(volume);
|
fControls->SetVolume(volume);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_CONTROLLER_MUTED_CHANGED: {
|
case MSG_CONTROLLER_MUTED_CHANGED:
|
||||||
|
{
|
||||||
bool muted;
|
bool muted;
|
||||||
if (msg->FindBool("muted", &muted) == B_OK)
|
if (msg->FindBool("muted", &muted) == B_OK)
|
||||||
fControls->SetMuted(muted);
|
fControls->SetMuted(muted);
|
||||||
@@ -481,7 +491,8 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
case M_FILE_NEWPLAYER:
|
case M_FILE_NEWPLAYER:
|
||||||
gMainApp->NewWindow();
|
gMainApp->NewWindow();
|
||||||
break;
|
break;
|
||||||
case M_FILE_OPEN: {
|
case M_FILE_OPEN:
|
||||||
|
{
|
||||||
BMessenger target(this);
|
BMessenger target(this);
|
||||||
BMessage result(B_REFS_RECEIVED);
|
BMessage result(B_REFS_RECEIVED);
|
||||||
BMessage appMessage(M_SHOW_OPEN_PANEL);
|
BMessage appMessage(M_SHOW_OPEN_PANEL);
|
||||||
@@ -499,6 +510,7 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
ShowPlaylistWindow();
|
ShowPlaylistWindow();
|
||||||
break;
|
break;
|
||||||
case B_ABOUT_REQUESTED:
|
case B_ABOUT_REQUESTED:
|
||||||
|
{
|
||||||
BAlert *alert;
|
BAlert *alert;
|
||||||
alert = new BAlert("about", NAME"\n\n Written by Marcus Overhagen "
|
alert = new BAlert("about", NAME"\n\n Written by Marcus Overhagen "
|
||||||
", Stephan Aßmus and Frederik Modéen", "Thanks");
|
", Stephan Aßmus and Frederik Modéen", "Thanks");
|
||||||
@@ -510,6 +522,7 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
alert->Go(NULL); // Asynchronous mode
|
alert->Go(NULL); // Asynchronous mode
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case M_FILE_CLOSE:
|
case M_FILE_CLOSE:
|
||||||
PostMessage(B_QUIT_REQUESTED);
|
PostMessage(B_QUIT_REQUESTED);
|
||||||
break;
|
break;
|
||||||
@@ -664,12 +677,13 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
case M_SET_PLAYLIST_POSITION: {
|
case M_SET_PLAYLIST_POSITION:
|
||||||
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
int32 index;
|
int32 index;
|
||||||
if (msg->FindInt32("index", &index) == B_OK)
|
if (msg->FindInt32("index", &index) == B_OK)
|
||||||
fPlaylist->SetCurrentRefIndex(index);
|
fPlaylist->SetCurrentItemIndex(index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,18 +745,18 @@ MainWin::QuitRequested()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MainWin::OpenFile(const entry_ref &ref)
|
MainWin::OpenPlaylistItem(const PlaylistItemRef& item)
|
||||||
{
|
{
|
||||||
printf("MainWin::OpenFile\n");
|
printf("MainWin::OpenPlaylistItem\n");
|
||||||
|
|
||||||
status_t err = fController->SetTo(ref);
|
status_t err = fController->SetTo(item);
|
||||||
if (err != B_OK) {
|
if (err != B_OK) {
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
if (fPlaylist->CountItems() == 1) {
|
if (fPlaylist->CountItems() == 1) {
|
||||||
// display error if this is the only file we're supposed to play
|
// display error if this is the only file we're supposed to play
|
||||||
BString message;
|
BString message;
|
||||||
message << "The file '";
|
message << "The file '";
|
||||||
message << ref.name;
|
message << item->Name();
|
||||||
message << "' could not be opened.\n\n";
|
message << "' could not be opened.\n\n";
|
||||||
|
|
||||||
if (err == B_MEDIA_NO_HANDLER) {
|
if (err == B_MEDIA_NO_HANDLER) {
|
||||||
@@ -757,7 +771,7 @@ MainWin::OpenFile(const entry_ref &ref)
|
|||||||
(new BAlert("error", message.String(), "OK"))->Go();
|
(new BAlert("error", message.String(), "OK"))->Go();
|
||||||
} else {
|
} else {
|
||||||
// just go to the next file and don't bother user
|
// just go to the next file and don't bother user
|
||||||
fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1);
|
fPlaylist->SetCurrentItemIndex(fPlaylist->CurrentItemIndex() + 1);
|
||||||
}
|
}
|
||||||
fHasFile = false;
|
fHasFile = false;
|
||||||
fHasVideo = false;
|
fHasVideo = false;
|
||||||
@@ -767,7 +781,7 @@ MainWin::OpenFile(const entry_ref &ref)
|
|||||||
fHasFile = true;
|
fHasFile = true;
|
||||||
fHasVideo = fController->VideoTrackCount() != 0;
|
fHasVideo = fController->VideoTrackCount() != 0;
|
||||||
fHasAudio = fController->AudioTrackCount() != 0;
|
fHasAudio = fController->AudioTrackCount() != 0;
|
||||||
SetTitle(ref.name);
|
SetTitle(item->Name().String());
|
||||||
}
|
}
|
||||||
_SetupWindow();
|
_SetupWindow();
|
||||||
}
|
}
|
||||||
@@ -1398,7 +1412,7 @@ MainWin::_KeyDown(BMessage *msg)
|
|||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
BMessage removeMessage(M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH);
|
BMessage removeMessage(M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH);
|
||||||
removeMessage.AddInt32("playlist index",
|
removeMessage.AddInt32("playlist index",
|
||||||
fPlaylist->CurrentRefIndex());
|
fPlaylist->CurrentItemIndex());
|
||||||
fPlaylistWindow->PostMessage(&removeMessage);
|
fPlaylistWindow->PostMessage(&removeMessage);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -1592,26 +1606,24 @@ MainWin::_UpdatePlaylistMenu()
|
|||||||
|
|
||||||
int32 count = fPlaylist->CountItems();
|
int32 count = fPlaylist->CountItems();
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
entry_ref ref;
|
PlaylistItem* item = fPlaylist->ItemAtFast(i);
|
||||||
if (fPlaylist->GetRefAt(i, &ref) < B_OK)
|
_AddPlaylistItem(item, i);
|
||||||
continue;
|
|
||||||
_AddPlaylistItem(ref, i);
|
|
||||||
}
|
}
|
||||||
fPlaylistMenu->SetTargetForItems(this);
|
fPlaylistMenu->SetTargetForItems(this);
|
||||||
|
|
||||||
_MarkPlaylistItem(fPlaylist->CurrentRefIndex());
|
_MarkPlaylistItem(fPlaylist->CurrentItemIndex());
|
||||||
|
|
||||||
fPlaylist->Unlock();
|
fPlaylist->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MainWin::_AddPlaylistItem(const entry_ref& ref, int32 index)
|
MainWin::_AddPlaylistItem(PlaylistItem* item, int32 index)
|
||||||
{
|
{
|
||||||
BMessage* message = new BMessage(M_SET_PLAYLIST_POSITION);
|
BMessage* message = new BMessage(M_SET_PLAYLIST_POSITION);
|
||||||
message->AddInt32("index", index);
|
message->AddInt32("index", index);
|
||||||
BMenuItem* item = new BMenuItem(ref.name, message);
|
BMenuItem* menuItem = new BMenuItem(item->Name().String(), message);
|
||||||
fPlaylistMenu->AddItem(item, index);
|
fPlaylistMenu->AddItem(menuItem, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* MainWin.h - Media Player for the Haiku Operating System
|
* MainWin.h - Media Player for the Haiku Operating System
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
||||||
* Copyright (C) 2007 Stephan Aßmus <superstippi@gmx.de>
|
* Copyright (C) 2007-2009 Stephan Aßmus <superstippi@gmx.de> (MIT ok)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "InfoWin.h"
|
#include "InfoWin.h"
|
||||||
#include "ListenerAdapter.h"
|
#include "ListenerAdapter.h"
|
||||||
#include "Playlist.h"
|
#include "Playlist.h"
|
||||||
|
#include "PlaylistItem.h"
|
||||||
#include "VideoView.h"
|
#include "VideoView.h"
|
||||||
|
|
||||||
class ControllerObserver;
|
class ControllerObserver;
|
||||||
@@ -51,7 +52,7 @@ public:
|
|||||||
virtual void WindowActivated(bool active);
|
virtual void WindowActivated(bool active);
|
||||||
virtual bool QuitRequested();
|
virtual bool QuitRequested();
|
||||||
|
|
||||||
void OpenFile(const entry_ref& ref);
|
void OpenPlaylistItem(const PlaylistItemRef& item);
|
||||||
|
|
||||||
void ShowFileInfo();
|
void ShowFileInfo();
|
||||||
void ShowPlaylistWindow();
|
void ShowPlaylistWindow();
|
||||||
@@ -89,7 +90,7 @@ private:
|
|||||||
|
|
||||||
void _UpdateControlsEnabledStatus();
|
void _UpdateControlsEnabledStatus();
|
||||||
void _UpdatePlaylistMenu();
|
void _UpdatePlaylistMenu();
|
||||||
void _AddPlaylistItem(const entry_ref& ref,
|
void _AddPlaylistItem(PlaylistItem* item,
|
||||||
int32 index);
|
int32 index);
|
||||||
void _RemovePlaylistItem(int32 index);
|
void _RemovePlaylistItem(int32 index);
|
||||||
void _MarkPlaylistItem(int32 index);
|
void _MarkPlaylistItem(int32 index);
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Haiku. All rights reserved.
|
* Copyright © 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CopyPLItemsCommand.h"
|
#include "CopyPLItemsCommand.h"
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
@@ -21,24 +17,31 @@ using std::nothrow;
|
|||||||
|
|
||||||
CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist,
|
CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist,
|
||||||
const int32* indices, int32 count, int32 toIndex)
|
const int32* indices, int32 count, int32 toIndex)
|
||||||
: Command()
|
:
|
||||||
, fPlaylist(playlist)
|
PLItemsCommand(),
|
||||||
, fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL)
|
fPlaylist(playlist),
|
||||||
, fToIndex(toIndex)
|
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
|
||||||
, fCount(count)
|
fToIndex(toIndex),
|
||||||
|
fCount(count),
|
||||||
|
fItemsCopied(false)
|
||||||
{
|
{
|
||||||
if (!indices || !fPlaylist || !fRefs) {
|
if (!indices || !fPlaylist || !fItems) {
|
||||||
// indicate a bad object state
|
// indicate a bad object state
|
||||||
delete[] fRefs;
|
delete[] fItems;
|
||||||
fRefs = NULL;
|
fItems = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(fItems, 0, sizeof(PlaylistItem*) * fCount);
|
||||||
|
|
||||||
// init original entries and
|
// init original entries and
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
if (fPlaylist->GetRefAt(indices[i], &fRefs[i]) < B_OK) {
|
PlaylistItem* item = fPlaylist->ItemAt(indices[i]);
|
||||||
delete[] fRefs;
|
if (item != NULL)
|
||||||
fRefs = NULL;
|
fItems[i] = item->Clone();
|
||||||
|
if (fItems[i] == NULL) {
|
||||||
|
// indicate a bad object state
|
||||||
|
_CleanUp(fItems, fCount, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,14 +50,14 @@ CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist,
|
|||||||
|
|
||||||
CopyPLItemsCommand::~CopyPLItemsCommand()
|
CopyPLItemsCommand::~CopyPLItemsCommand()
|
||||||
{
|
{
|
||||||
delete[] fRefs;
|
_CleanUp(fItems, fCount, !fItemsCopied);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
CopyPLItemsCommand::InitCheck()
|
CopyPLItemsCommand::InitCheck()
|
||||||
{
|
{
|
||||||
if (!fPlaylist || !fRefs)
|
if (!fPlaylist || !fItems)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -67,18 +70,17 @@ CopyPLItemsCommand::Perform()
|
|||||||
|
|
||||||
status_t ret = B_OK;
|
status_t ret = B_OK;
|
||||||
|
|
||||||
|
fItemsCopied = true;
|
||||||
|
|
||||||
// add refs to playlist at the insertion index
|
// add refs to playlist at the insertion index
|
||||||
int32 index = fToIndex;
|
int32 index = fToIndex;
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
if (!fPlaylist->AddRef(fRefs[i], index++)) {
|
if (!fPlaylist->AddItem(fItems[i], index++)) {
|
||||||
ret = B_NO_MEMORY;
|
ret = B_NO_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -87,20 +89,19 @@ CopyPLItemsCommand::Undo()
|
|||||||
{
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
// remember currently playling ref in case we copy items over it
|
fItemsCopied = false;
|
||||||
entry_ref currentRef;
|
// remember currently playling item in case we copy items over it
|
||||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||||
¤tRef) == B_OK;
|
|
||||||
|
|
||||||
// remove refs from playlist
|
// remove refs from playlist
|
||||||
int32 index = fToIndex;
|
int32 index = fToIndex;
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
fPlaylist->RemoveRef(index++, false);
|
fPlaylist->RemoveItem(index++, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// take care about currently played ref
|
// take care about currently played item
|
||||||
if (adjustCurrentRef)
|
if (current != NULL)
|
||||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Haiku. All rights reserved.
|
* Copyright © 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
#ifndef COPY_PL_ITEMS_COMMAND_H
|
#ifndef COPY_PL_ITEMS_COMMAND_H
|
||||||
#define COPY_PL_ITEMS_COMMAND_H
|
#define COPY_PL_ITEMS_COMMAND_H
|
||||||
|
|
||||||
|
|
||||||
#include "Command.h"
|
#include "PLItemsCommand.h"
|
||||||
|
|
||||||
class Playlist;
|
class CopyPLItemsCommand : public PLItemsCommand {
|
||||||
struct entry_ref;
|
|
||||||
|
|
||||||
class CopyPLItemsCommand : public Command {
|
|
||||||
public:
|
public:
|
||||||
CopyPLItemsCommand(
|
CopyPLItemsCommand(
|
||||||
Playlist* playlist,
|
Playlist* playlist,
|
||||||
@@ -32,9 +26,10 @@ class CopyPLItemsCommand : public Command {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Playlist* fPlaylist;
|
Playlist* fPlaylist;
|
||||||
entry_ref* fRefs;
|
PlaylistItem** fItems;
|
||||||
int32 fToIndex;
|
int32 fToIndex;
|
||||||
int32 fCount;
|
int32 fCount;
|
||||||
|
bool fItemsCopied;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COPY_PL_ITEMS_COMMAND_H
|
#endif // COPY_PL_ITEMS_COMMAND_H
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009 Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT license.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "EntryRefPlaylistItem.h"
|
|
||||||
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
#include <MediaFile.h>
|
|
||||||
|
|
||||||
|
|
||||||
EntryRefPlaylistItem::EntryRefPlaylistItem(const entry_ref& ref)
|
|
||||||
:
|
|
||||||
fRef(ref)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EntryRefPlaylistItem::~EntryRefPlaylistItem()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::SetName(const BString& name)
|
|
||||||
{
|
|
||||||
BEntry entry(&fRef);
|
|
||||||
|
|
||||||
status_t ret = entry.Rename(name.String(), false);
|
|
||||||
if (ret != B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
entry.GetRef(&fRef);
|
|
||||||
_NotifyListeners();
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::GetName(BString& name) const
|
|
||||||
{
|
|
||||||
name = fRef.name;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::SetTitle(const BString& title)
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::GetTitle(BString& title) const
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::SetAuthor(const BString& author)
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::GetAuthor(BString& author) const
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::SetAlbum(const BString& album)
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::GetAlbum(BString& album) const
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::SetTrackNumber(int32 trackNumber)
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::GetTrackNumber(int32& trackNumber) const
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::SetBitRate(int32 bitRate)
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::GetBitRate(int32& bitRate) const
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::GetDuration(bigtime_t& duration) const
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::MoveIntoTrash()
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
EntryRefPlaylistItem::RestoreFromTrash()
|
|
||||||
{
|
|
||||||
return B_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
BMediaFile*
|
|
||||||
EntryRefPlaylistItem::CreateMediaFile() const
|
|
||||||
{
|
|
||||||
return new (std::nothrow) BMediaFile(&fRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009 Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT license.
|
|
||||||
*/
|
|
||||||
#ifndef ENTRY_REF_PLAYLIST_ITEM_H
|
|
||||||
#define ENTRY_REF_PLAYLIST_ITEM_H
|
|
||||||
|
|
||||||
#include "PlaylistItem.h"
|
|
||||||
|
|
||||||
#include <Entry.h>
|
|
||||||
|
|
||||||
class EntryRefPlaylistItem : public PlaylistItem {
|
|
||||||
public:
|
|
||||||
EntryRefPlaylistItem(const entry_ref& ref);
|
|
||||||
virtual ~EntryRefPlaylistItem();
|
|
||||||
|
|
||||||
// archiving
|
|
||||||
// virtual status_t Unarchive(const BMessage* archive);
|
|
||||||
// virtual status_t Archive(BMessage* into) const;
|
|
||||||
//
|
|
||||||
// virtual status_t Unflatten(BDataIO* stream);
|
|
||||||
// virtual status_t Flatten(BDataIO* stream) const;
|
|
||||||
|
|
||||||
// properties
|
|
||||||
virtual status_t SetName(const BString& name);
|
|
||||||
virtual status_t GetName(BString& name) const;
|
|
||||||
|
|
||||||
virtual status_t SetTitle(const BString& title);
|
|
||||||
virtual status_t GetTitle(BString& title) const;
|
|
||||||
|
|
||||||
virtual status_t SetAuthor(const BString& author);
|
|
||||||
virtual status_t GetAuthor(BString& author) const;
|
|
||||||
|
|
||||||
virtual status_t SetAlbum(const BString& album);
|
|
||||||
virtual status_t GetAlbum(BString& album) const;
|
|
||||||
|
|
||||||
virtual status_t SetTrackNumber(int32 trackNumber);
|
|
||||||
virtual status_t GetTrackNumber(int32& trackNumber) const;
|
|
||||||
|
|
||||||
virtual status_t SetBitRate(int32 bitRate);
|
|
||||||
virtual status_t GetBitRate(int32& bitRate) const;
|
|
||||||
|
|
||||||
virtual status_t GetDuration(bigtime_t& duration) const;
|
|
||||||
|
|
||||||
// methods
|
|
||||||
virtual status_t MoveIntoTrash();
|
|
||||||
virtual status_t RestoreFromTrash();
|
|
||||||
|
|
||||||
// playback
|
|
||||||
virtual BMediaFile* CreateMediaFile() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
entry_ref fRef;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ENTRY_REF_PLAYLIST_ITEM_H
|
|
||||||
@@ -0,0 +1,300 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2009 Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FilePlaylistItem.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <Directory.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <MediaFile.h>
|
||||||
|
#include <Path.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const char* kPathKey = "path";
|
||||||
|
|
||||||
|
|
||||||
|
FilePlaylistItem::FilePlaylistItem(const entry_ref& ref)
|
||||||
|
:
|
||||||
|
fRef(ref),
|
||||||
|
fNameInTrash("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FilePlaylistItem::FilePlaylistItem(const FilePlaylistItem& other)
|
||||||
|
:
|
||||||
|
fRef(other.fRef),
|
||||||
|
fNameInTrash(other.fNameInTrash)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FilePlaylistItem::FilePlaylistItem(const BMessage* archive)
|
||||||
|
:
|
||||||
|
fRef(),
|
||||||
|
fNameInTrash("")
|
||||||
|
{
|
||||||
|
const char* path;
|
||||||
|
if (archive != NULL && archive->FindString(kPathKey, &path) == B_OK) {
|
||||||
|
if (get_ref_for_path(path, &fRef) != B_OK)
|
||||||
|
fRef = entry_ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FilePlaylistItem::~FilePlaylistItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PlaylistItem*
|
||||||
|
FilePlaylistItem::Clone() const
|
||||||
|
{
|
||||||
|
return new (std::nothrow) FilePlaylistItem(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BArchivable*
|
||||||
|
FilePlaylistItem::Instantiate(BMessage* archive)
|
||||||
|
{
|
||||||
|
if (validate_instantiation(archive, "FilePlaylistItem"))
|
||||||
|
return new (std::nothrow) FilePlaylistItem(archive);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t ret = BArchivable::Archive(into, deep);
|
||||||
|
if (ret != B_OK)
|
||||||
|
return ret;
|
||||||
|
BPath path(&fRef);
|
||||||
|
ret = path.InitCheck();
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = into->AddString(kPathKey, path.Path());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::SetAttribute(const Attribute& attribute,
|
||||||
|
const BString& string)
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::GetAttribute(const Attribute& attribute,
|
||||||
|
BString& string) const
|
||||||
|
{
|
||||||
|
if (attribute == ATTR_STRING_NAME) {
|
||||||
|
string = fRef.name;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::SetAttribute(const Attribute& attribute,
|
||||||
|
const int32& value)
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::GetAttribute(const Attribute& attribute,
|
||||||
|
int32& value) const
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::SetAttribute(const Attribute& attribute,
|
||||||
|
const int64& value)
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::GetAttribute(const Attribute& attribute,
|
||||||
|
int64& value) const
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
FilePlaylistItem::LocationURI() const
|
||||||
|
{
|
||||||
|
BPath path(&fRef);
|
||||||
|
BString locationURI("file://");
|
||||||
|
locationURI << path.Path();
|
||||||
|
return locationURI;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::GetIcon(BBitmap* bitmap, icon_size iconSize) const
|
||||||
|
{
|
||||||
|
BNode node(&fRef);
|
||||||
|
BNodeInfo info(&node);
|
||||||
|
return info.GetTrackerIcon(bitmap, iconSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::MoveIntoTrash()
|
||||||
|
{
|
||||||
|
if (fNameInTrash.Length() != 0) {
|
||||||
|
// Already in the trash!
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
char trashPath[B_PATH_NAME_LENGTH];
|
||||||
|
status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device,
|
||||||
|
true /*create it*/, trashPath, B_PATH_NAME_LENGTH);
|
||||||
|
if (err != B_OK) {
|
||||||
|
fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
BEntry entry(&fRef);
|
||||||
|
err = entry.InitCheck();
|
||||||
|
if (err != B_OK) {
|
||||||
|
fprintf(stderr, "failed to init BEntry for %s: %s\n",
|
||||||
|
fRef.name, strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
BDirectory trashDir(trashPath);
|
||||||
|
if (err != B_OK) {
|
||||||
|
fprintf(stderr, "failed to init BDirectory for %s: %s\n",
|
||||||
|
trashPath, strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a unique name for the entry in the trash
|
||||||
|
fNameInTrash = fRef.name;
|
||||||
|
int32 uniqueNameIndex = 1;
|
||||||
|
while (true) {
|
||||||
|
BEntry test(&trashDir, fNameInTrash.String());
|
||||||
|
if (!test.Exists())
|
||||||
|
break;
|
||||||
|
fNameInTrash = fRef.name;
|
||||||
|
fNameInTrash << ' ' << uniqueNameIndex;
|
||||||
|
uniqueNameIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember the original path
|
||||||
|
BPath originalPath;
|
||||||
|
entry.GetPath(&originalPath);
|
||||||
|
|
||||||
|
// Finally, move the entry into the trash
|
||||||
|
err = entry.MoveTo(&trashDir, fNameInTrash.String());
|
||||||
|
if (err != B_OK) {
|
||||||
|
fprintf(stderr, "failed to move entry into trash %s: %s\n",
|
||||||
|
trashPath, strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow Tracker to restore this entry
|
||||||
|
BNode node(&entry);
|
||||||
|
BString originalPathString(originalPath.Path());
|
||||||
|
node.WriteAttrString("_trk/original_path", &originalPathString);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FilePlaylistItem::RestoreFromTrash()
|
||||||
|
{
|
||||||
|
if (fNameInTrash.Length() <= 0) {
|
||||||
|
// Not in the trash!
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
char trashPath[B_PATH_NAME_LENGTH];
|
||||||
|
status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device,
|
||||||
|
false /*create it*/, trashPath, B_PATH_NAME_LENGTH);
|
||||||
|
if (err != B_OK) {
|
||||||
|
fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
// construct the entry to the file in the trash
|
||||||
|
// TODO: BEntry(const BDirectory* directory, const char* path) is broken!
|
||||||
|
// BEntry entry(trashPath, fNamesInTrash[i].String());
|
||||||
|
BPath path(trashPath, fNameInTrash.String());
|
||||||
|
BEntry entry(path.Path());
|
||||||
|
err = entry.InitCheck();
|
||||||
|
if (err != B_OK) {
|
||||||
|
fprintf(stderr, "failed to init BEntry for %s: %s\n",
|
||||||
|
fNameInTrash.String(), strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
//entry.GetPath(&path);
|
||||||
|
//printf("moving '%s'\n", path.Path());
|
||||||
|
|
||||||
|
// construct the folder of the original entry_ref
|
||||||
|
node_ref nodeRef;
|
||||||
|
nodeRef.device = fRef.device;
|
||||||
|
nodeRef.node = fRef.directory;
|
||||||
|
BDirectory originalDir(&nodeRef);
|
||||||
|
err = originalDir.InitCheck();
|
||||||
|
if (err != B_OK) {
|
||||||
|
fprintf(stderr, "failed to init original BDirectory for "
|
||||||
|
"%s: %s\n", fRef.name, strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
//path.SetTo(&originalDir, fItems[i].name);
|
||||||
|
//printf("as '%s'\n", path.Path());
|
||||||
|
|
||||||
|
// Reset the name here, the user may have already moved the entry
|
||||||
|
// out of the trash via Tracker for example.
|
||||||
|
fNameInTrash = "";
|
||||||
|
|
||||||
|
// Finally, move the entry back into the original folder
|
||||||
|
err = entry.MoveTo(&originalDir, fRef.name);
|
||||||
|
if (err != B_OK) {
|
||||||
|
fprintf(stderr, "failed to restore entry from trash "
|
||||||
|
"%s: %s\n", fRef.name, strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the attribute that helps Tracker restore the entry.
|
||||||
|
BNode node(&entry);
|
||||||
|
node.RemoveAttr("_trk/original_path");
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
BMediaFile*
|
||||||
|
FilePlaylistItem::CreateMediaFile() const
|
||||||
|
{
|
||||||
|
return new (std::nothrow) BMediaFile(&fRef);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2009 Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef FILE_PLAYLIST_ITEM_H
|
||||||
|
#define FILE_PLAYLIST_ITEM_H
|
||||||
|
|
||||||
|
#include "PlaylistItem.h"
|
||||||
|
|
||||||
|
#include <Entry.h>
|
||||||
|
|
||||||
|
class FilePlaylistItem : public PlaylistItem {
|
||||||
|
public:
|
||||||
|
FilePlaylistItem(const entry_ref& ref);
|
||||||
|
FilePlaylistItem(const FilePlaylistItem& item);
|
||||||
|
FilePlaylistItem(const BMessage* archive);
|
||||||
|
virtual ~FilePlaylistItem();
|
||||||
|
|
||||||
|
virtual PlaylistItem* Clone() const;
|
||||||
|
|
||||||
|
// archiving
|
||||||
|
static BArchivable* Instantiate(BMessage* archive);
|
||||||
|
virtual status_t Archive(BMessage* into,
|
||||||
|
bool deep = true) const;
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
virtual status_t SetAttribute(const Attribute& attribute,
|
||||||
|
const BString& string);
|
||||||
|
virtual status_t GetAttribute(const Attribute& attribute,
|
||||||
|
BString& string) const;
|
||||||
|
|
||||||
|
virtual status_t SetAttribute(const Attribute& attribute,
|
||||||
|
const int32& value);
|
||||||
|
virtual status_t GetAttribute(const Attribute& attribute,
|
||||||
|
int32& value) const;
|
||||||
|
|
||||||
|
virtual status_t SetAttribute(const Attribute& attribute,
|
||||||
|
const int64& value);
|
||||||
|
virtual status_t GetAttribute(const Attribute& attribute,
|
||||||
|
int64& value) const;
|
||||||
|
|
||||||
|
// methods
|
||||||
|
virtual BString LocationURI() const;
|
||||||
|
virtual status_t GetIcon(BBitmap* bitmap,
|
||||||
|
icon_size iconSize) const;
|
||||||
|
|
||||||
|
virtual status_t MoveIntoTrash();
|
||||||
|
virtual status_t RestoreFromTrash();
|
||||||
|
|
||||||
|
// playback
|
||||||
|
virtual BMediaFile* CreateMediaFile() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
entry_ref fRef;
|
||||||
|
BString fNameInTrash;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILE_PLAYLIST_ITEM_H
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Haiku. All rights reserved.
|
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ImportPLItemsCommand.h"
|
#include "ImportPLItemsCommand.h"
|
||||||
@@ -15,6 +12,7 @@
|
|||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
|
|
||||||
#include "Playlist.h"
|
#include "Playlist.h"
|
||||||
|
#include "PlaylistItem.h"
|
||||||
|
|
||||||
|
|
||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
@@ -22,16 +20,20 @@ using std::nothrow;
|
|||||||
|
|
||||||
ImportPLItemsCommand::ImportPLItemsCommand(Playlist* playlist,
|
ImportPLItemsCommand::ImportPLItemsCommand(Playlist* playlist,
|
||||||
const BMessage* refsMessage, int32 toIndex)
|
const BMessage* refsMessage, int32 toIndex)
|
||||||
: Command()
|
:
|
||||||
, fPlaylist(playlist)
|
PLItemsCommand(),
|
||||||
|
fPlaylist(playlist),
|
||||||
|
|
||||||
, fOldRefs(NULL)
|
fOldItems(NULL),
|
||||||
, fOldCount(0)
|
fOldCount(0),
|
||||||
|
|
||||||
, fNewRefs(NULL)
|
fNewItems(NULL),
|
||||||
, fNewCount(0)
|
fNewCount(0),
|
||||||
|
|
||||||
, fToIndex(toIndex)
|
fToIndex(toIndex),
|
||||||
|
fPlaylingIndex(0),
|
||||||
|
|
||||||
|
fItemsAdded(false)
|
||||||
{
|
{
|
||||||
if (!fPlaylist)
|
if (!fPlaylist)
|
||||||
return;
|
return;
|
||||||
@@ -47,38 +49,40 @@ ImportPLItemsCommand::ImportPLItemsCommand(Playlist* playlist,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fNewRefs = new (nothrow) entry_ref[fNewCount];
|
fNewItems = new (nothrow) PlaylistItem*[fNewCount];
|
||||||
if (!fNewRefs)
|
if (!fNewItems)
|
||||||
return;
|
return;
|
||||||
|
memset(fNewItems, 0, fNewCount * sizeof(PlaylistItem*));
|
||||||
|
|
||||||
// init new entries
|
// init new entries
|
||||||
for (int32 i = 0; i < fNewCount; i++) {
|
for (int32 i = 0; i < fNewCount; i++) {
|
||||||
if (temp.GetRefAt(i, &fNewRefs[i]) < B_OK) {
|
fNewItems[i] = temp.ItemAtFast(i)->Clone();
|
||||||
|
if (fNewItems[i] == NULL) {
|
||||||
// indicate bad object init
|
// indicate bad object init
|
||||||
delete[] fNewRefs;
|
_CleanUp(fNewItems, fNewCount, true);
|
||||||
fNewRefs = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fPlaylingIndex = fPlaylist->CurrentItemIndex();
|
||||||
|
|
||||||
if (fToIndex < 0) {
|
if (fToIndex < 0) {
|
||||||
fOldCount = fPlaylist->CountItems();
|
fOldCount = fPlaylist->CountItems();
|
||||||
if (fOldCount > 0) {
|
if (fOldCount > 0) {
|
||||||
fOldRefs = new (nothrow) entry_ref[fOldCount];
|
fOldItems = new (nothrow) PlaylistItem*[fOldCount];
|
||||||
if (!fOldRefs) {
|
if (!fOldItems) {
|
||||||
// indicate bad object init
|
// indicate bad object init
|
||||||
delete[] fNewRefs;
|
_CleanUp(fNewItems, fNewCount, true);
|
||||||
fNewRefs = NULL;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
memset(fOldItems, 0, fOldCount * sizeof(PlaylistItem*));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32 i = 0; i < fOldCount; i++) {
|
for (int32 i = 0; i < fOldCount; i++) {
|
||||||
if (fPlaylist->GetRefAt(i, &fOldRefs[i]) < B_OK) {
|
fOldItems[i] = fPlaylist->ItemAtFast(i)->Clone();
|
||||||
|
if (fOldItems[i] == NULL) {
|
||||||
// indicate bad object init
|
// indicate bad object init
|
||||||
delete[] fNewRefs;
|
_CleanUp(fNewItems, fNewCount, true);
|
||||||
fNewRefs = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,15 +91,15 @@ ImportPLItemsCommand::ImportPLItemsCommand(Playlist* playlist,
|
|||||||
|
|
||||||
ImportPLItemsCommand::~ImportPLItemsCommand()
|
ImportPLItemsCommand::~ImportPLItemsCommand()
|
||||||
{
|
{
|
||||||
delete[] fOldRefs;
|
_CleanUp(fOldItems, fOldCount, fItemsAdded);
|
||||||
delete[] fNewRefs;
|
_CleanUp(fNewItems, fNewCount, !fItemsAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ImportPLItemsCommand::InitCheck()
|
ImportPLItemsCommand::InitCheck()
|
||||||
{
|
{
|
||||||
if (!fPlaylist || !fNewRefs)
|
if (!fPlaylist || !fNewItems)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -106,9 +110,11 @@ ImportPLItemsCommand::Perform()
|
|||||||
{
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
|
fItemsAdded = true;
|
||||||
|
|
||||||
int32 index = fToIndex;
|
int32 index = fToIndex;
|
||||||
if (fToIndex < 0) {
|
if (fToIndex < 0) {
|
||||||
fPlaylist->MakeEmpty();
|
fPlaylist->MakeEmpty(false);
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,13 +122,13 @@ ImportPLItemsCommand::Perform()
|
|||||||
|
|
||||||
// add refs to playlist at the insertion index
|
// add refs to playlist at the insertion index
|
||||||
for (int32 i = 0; i < fNewCount; i++) {
|
for (int32 i = 0; i < fNewCount; i++) {
|
||||||
if (!fPlaylist->AddRef(fNewRefs[i], index++))
|
if (!fPlaylist->AddItem(fNewItems[i], index++))
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startPlaying) {
|
if (startPlaying) {
|
||||||
// open first file
|
// open first file
|
||||||
fPlaylist->SetCurrentRefIndex(0);
|
fPlaylist->SetCurrentItemIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -134,17 +140,22 @@ ImportPLItemsCommand::Undo()
|
|||||||
{
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
|
fItemsAdded = false;
|
||||||
|
|
||||||
if (fToIndex < 0) {
|
if (fToIndex < 0) {
|
||||||
// remove new refs from playlist and restore old refs
|
// remove new items from playlist and restore old refs
|
||||||
fPlaylist->MakeEmpty();
|
fPlaylist->MakeEmpty(false);
|
||||||
for (int32 i = 0; i < fOldCount; i++) {
|
for (int32 i = 0; i < fOldCount; i++) {
|
||||||
if (!fPlaylist->AddRef(fOldRefs[i], i))
|
if (!fPlaylist->AddItem(fOldItems[i], i))
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
// Restore previously playing item
|
||||||
|
if (fPlaylingIndex >= 0)
|
||||||
|
fPlaylist->SetCurrentItemIndex(fPlaylingIndex);
|
||||||
} else {
|
} else {
|
||||||
// remove refs from playlist
|
// remove new items from playlist
|
||||||
for (int32 i = 0; i < fNewCount; i++) {
|
for (int32 i = 0; i < fNewCount; i++) {
|
||||||
fPlaylist->RemoveRef(fToIndex);
|
fPlaylist->RemoveItem(fToIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,3 +171,4 @@ ImportPLItemsCommand::GetName(BString& name)
|
|||||||
else
|
else
|
||||||
name << "Import Entry";
|
name << "Import Entry";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Haiku. All rights reserved.
|
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
#ifndef IMPORT_PL_ITEMS_COMMAND_H
|
#ifndef IMPORT_PL_ITEMS_COMMAND_H
|
||||||
#define IMPORT_PL_ITEMS_COMMAND_H
|
#define IMPORT_PL_ITEMS_COMMAND_H
|
||||||
|
|
||||||
|
|
||||||
#include "Command.h"
|
#include "PLItemsCommand.h"
|
||||||
|
|
||||||
class BMessage;
|
class BMessage;
|
||||||
class Playlist;
|
|
||||||
struct entry_ref;
|
|
||||||
|
|
||||||
class ImportPLItemsCommand : public Command {
|
class ImportPLItemsCommand : public PLItemsCommand {
|
||||||
public:
|
public:
|
||||||
ImportPLItemsCommand(
|
ImportPLItemsCommand(
|
||||||
Playlist* playlist,
|
Playlist* playlist,
|
||||||
@@ -32,11 +27,13 @@ class ImportPLItemsCommand : public Command {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Playlist* fPlaylist;
|
Playlist* fPlaylist;
|
||||||
entry_ref* fOldRefs;
|
PlaylistItem** fOldItems;
|
||||||
int32 fOldCount;
|
int32 fOldCount;
|
||||||
entry_ref* fNewRefs;
|
PlaylistItem** fNewItems;
|
||||||
int32 fNewCount;
|
int32 fNewCount;
|
||||||
int32 fToIndex;
|
int32 fToIndex;
|
||||||
|
int32 fPlaylingIndex;
|
||||||
|
bool fItemsAdded;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IMPORT_PL_ITEMS_COMMAND_H
|
#endif // IMPORT_PL_ITEMS_COMMAND_H
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Haiku. All rights reserved.
|
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MovePLItemsCommand.h"
|
#include "MovePLItemsCommand.h"
|
||||||
@@ -21,20 +18,22 @@ using std::nothrow;
|
|||||||
|
|
||||||
MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
|
MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
|
||||||
const int32* indices, int32 count, int32 toIndex)
|
const int32* indices, int32 count, int32 toIndex)
|
||||||
: Command()
|
:
|
||||||
, fPlaylist(playlist)
|
PLItemsCommand(),
|
||||||
, fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL)
|
fPlaylist(playlist),
|
||||||
, fIndices(count > 0 ? new (nothrow) int32[count] : NULL)
|
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
|
||||||
, fToIndex(toIndex)
|
fIndices(count > 0 ? new (nothrow) int32[count] : NULL),
|
||||||
, fCount(count)
|
fToIndex(toIndex),
|
||||||
|
fCount(count)
|
||||||
{
|
{
|
||||||
if (!indices || !fPlaylist || !fRefs || !fIndices) {
|
if (!indices || !fPlaylist || !fItems || !fIndices) {
|
||||||
// indicate a bad object state
|
// indicate a bad object state
|
||||||
delete[] fRefs;
|
delete[] fItems;
|
||||||
fRefs = NULL;
|
fItems = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(fItems, 0, sizeof(PlaylistItem*) * fCount);
|
||||||
memcpy(fIndices, indices, fCount * sizeof(int32));
|
memcpy(fIndices, indices, fCount * sizeof(int32));
|
||||||
|
|
||||||
// init original entry indices and
|
// init original entry indices and
|
||||||
@@ -42,10 +41,11 @@ MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
|
|||||||
// 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++) {
|
||||||
if (fPlaylist->GetRefAt(fIndices[i], &fRefs[i]) < B_OK) {
|
fItems[i] = fPlaylist->ItemAt(fIndices[i]);
|
||||||
|
if (fItems[i] == NULL) {
|
||||||
// indicate a bad object state
|
// indicate a bad object state
|
||||||
delete[] fRefs;
|
delete[] fItems;
|
||||||
fRefs = NULL;
|
fItems = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (fIndices[i] < fToIndex)
|
if (fIndices[i] < fToIndex)
|
||||||
@@ -57,7 +57,7 @@ MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
|
|||||||
|
|
||||||
MovePLItemsCommand::~MovePLItemsCommand()
|
MovePLItemsCommand::~MovePLItemsCommand()
|
||||||
{
|
{
|
||||||
delete[] fRefs;
|
delete[] fItems;
|
||||||
delete[] fIndices;
|
delete[] fIndices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ MovePLItemsCommand::~MovePLItemsCommand()
|
|||||||
status_t
|
status_t
|
||||||
MovePLItemsCommand::InitCheck()
|
MovePLItemsCommand::InitCheck()
|
||||||
{
|
{
|
||||||
if (!fRefs)
|
if (!fItems)
|
||||||
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
|
||||||
@@ -106,21 +106,19 @@ MovePLItemsCommand::Perform()
|
|||||||
|
|
||||||
status_t ret = B_OK;
|
status_t ret = B_OK;
|
||||||
|
|
||||||
// remember currently playling ref in case we move it
|
// remember currently playling item in case we move it
|
||||||
entry_ref currentRef;
|
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
|
||||||
¤tRef) == B_OK;
|
|
||||||
|
|
||||||
// remove refs from playlist
|
// remove refs from playlist
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
// "- i" to account for the items already removed
|
// "- i" to account for the items already removed
|
||||||
fPlaylist->RemoveRef(fIndices[i] - i, false);
|
fPlaylist->RemoveItem(fIndices[i] - i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add refs to playlist at the insertion index
|
// add refs to playlist at the insertion index
|
||||||
int32 index = fToIndex;
|
int32 index = fToIndex;
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
if (!fPlaylist->AddRef(fRefs[i], index++)) {
|
if (!fPlaylist->AddItem(fItems[i], index++)) {
|
||||||
ret = B_NO_MEMORY;
|
ret = B_NO_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -128,9 +126,9 @@ MovePLItemsCommand::Perform()
|
|||||||
if (ret < B_OK)
|
if (ret < B_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
// take care about currently played ref
|
// take care about currently played item
|
||||||
if (adjustCurrentRef)
|
if (current != NULL)
|
||||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -143,20 +141,18 @@ MovePLItemsCommand::Undo()
|
|||||||
|
|
||||||
status_t ret = B_OK;
|
status_t ret = B_OK;
|
||||||
|
|
||||||
// remember currently playling ref in case we move it
|
// remember currently playling item in case we move it
|
||||||
entry_ref currentRef;
|
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
|
||||||
¤tRef) == B_OK;
|
|
||||||
|
|
||||||
// remove refs from playlist
|
// remove refs from playlist
|
||||||
int32 index = fToIndex;
|
int32 index = fToIndex;
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
fPlaylist->RemoveRef(index++, false);
|
fPlaylist->RemoveItem(index++, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add ref to playlist at remembered indices
|
// add ref to playlist at remembered indices
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
if (!fPlaylist->AddRef(fRefs[i], fIndices[i])) {
|
if (!fPlaylist->AddItem(fItems[i], fIndices[i])) {
|
||||||
ret = B_NO_MEMORY;
|
ret = B_NO_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -164,9 +160,9 @@ MovePLItemsCommand::Undo()
|
|||||||
if (ret < B_OK)
|
if (ret < B_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
// take care about currently played ref
|
// take care about currently played item
|
||||||
if (adjustCurrentRef)
|
if (current != NULL)
|
||||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Haiku. All rights reserved.
|
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
#ifndef MOVE_PL_ITEMS_COMMAND_H
|
#ifndef MOVE_PL_ITEMS_COMMAND_H
|
||||||
#define MOVE_PL_ITEMS_COMMAND_H
|
#define MOVE_PL_ITEMS_COMMAND_H
|
||||||
|
|
||||||
|
|
||||||
#include "Command.h"
|
#include "PLItemsCommand.h"
|
||||||
|
|
||||||
class Playlist;
|
class MovePLItemsCommand : public PLItemsCommand {
|
||||||
struct entry_ref;
|
|
||||||
|
|
||||||
class MovePLItemsCommand : public Command {
|
|
||||||
public:
|
public:
|
||||||
MovePLItemsCommand(
|
MovePLItemsCommand(
|
||||||
Playlist* playlist,
|
Playlist* playlist,
|
||||||
@@ -32,7 +26,7 @@ class MovePLItemsCommand : public Command {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Playlist* fPlaylist;
|
Playlist* fPlaylist;
|
||||||
entry_ref* fRefs;
|
PlaylistItem** fItems;
|
||||||
int32* fIndices;
|
int32* fIndices;
|
||||||
int32 fToIndex;
|
int32 fToIndex;
|
||||||
int32 fCount;
|
int32 fCount;
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PLItemsCommand.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "Playlist.h"
|
||||||
|
#include "PlaylistItem.h"
|
||||||
|
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
|
||||||
|
PLItemsCommand::PLItemsCommand()
|
||||||
|
:
|
||||||
|
Command()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PLItemsCommand::~PLItemsCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PLItemsCommand::_CleanUp(PlaylistItem**& items, int32 count, bool deleteItems)
|
||||||
|
{
|
||||||
|
if (items == NULL)
|
||||||
|
return;
|
||||||
|
if (deleteItems) {
|
||||||
|
for (int32 i = 0; i < count; i++)
|
||||||
|
items[i]->RemoveReference();
|
||||||
|
}
|
||||||
|
delete[] items;
|
||||||
|
items = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef PL_ITEMS_COMMAND_H
|
||||||
|
#define PL_ITEMS_COMMAND_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "Command.h"
|
||||||
|
|
||||||
|
class Playlist;
|
||||||
|
class PlaylistItem;
|
||||||
|
|
||||||
|
class PLItemsCommand : public Command {
|
||||||
|
public:
|
||||||
|
PLItemsCommand();
|
||||||
|
virtual ~PLItemsCommand();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _CleanUp(PlaylistItem**& items, int32 count,
|
||||||
|
bool deleteItems);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PL_ITEMS_COMMAND_H
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* Playlist.cpp - Media Player for the Haiku Operating System
|
* Playlist.cpp - Media Player for the Haiku Operating System
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
||||||
* Copyright (C) 2007 Stephan Aßmus <superstippi@gmx.de>
|
* Copyright (C) 2007-2009 Stephan Aßmus <superstippi@gmx.de> (MIT ok)
|
||||||
* Copyright (C) 2008-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok)
|
* Copyright (C) 2008-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@@ -19,21 +19,27 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Playlist.h"
|
#include "Playlist.h"
|
||||||
|
|
||||||
#include <debugger.h>
|
#include <debugger.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <AppFileInfo.h>
|
||||||
|
#include <Application.h>
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
|
#include <Entry.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <Mime.h>
|
#include <Mime.h>
|
||||||
#include <NodeInfo.h>
|
#include <NodeInfo.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
|
#include <Roster.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "FilePlaylistItem.h"
|
||||||
#include "FileReadWrite.h"
|
#include "FileReadWrite.h"
|
||||||
|
|
||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
@@ -42,19 +48,54 @@ using std::nothrow;
|
|||||||
|
|
||||||
Playlist::Listener::Listener() {}
|
Playlist::Listener::Listener() {}
|
||||||
Playlist::Listener::~Listener() {}
|
Playlist::Listener::~Listener() {}
|
||||||
void Playlist::Listener::RefAdded(const entry_ref& ref, int32 index) {}
|
void Playlist::Listener::ItemAdded(PlaylistItem* item, int32 index) {}
|
||||||
void Playlist::Listener::RefRemoved(int32 index) {}
|
void Playlist::Listener::ItemRemoved(int32 index) {}
|
||||||
void Playlist::Listener::RefsSorted() {}
|
void Playlist::Listener::ItemsSorted() {}
|
||||||
void Playlist::Listener::CurrentRefChanged(int32 newIndex) {}
|
void Playlist::Listener::CurrentItemChanged(int32 newIndex) {}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
make_item_compare_string(const PlaylistItem* item, char* buffer,
|
||||||
|
size_t bufferSize)
|
||||||
|
{
|
||||||
|
// TODO: Maybe "location" would be useful here as well.
|
||||||
|
// snprintf(buffer, bufferSize, "%s - %s - %0*ld - %s",
|
||||||
|
// item->Author().String(),
|
||||||
|
// item->Album().String(),
|
||||||
|
// 3, item->TrackNumber(),
|
||||||
|
// item->Title().String());
|
||||||
|
snprintf(buffer, bufferSize, "%s", item->LocationURI().String());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
playlist_item_compare(const void* _item1, const void* _item2)
|
||||||
|
{
|
||||||
|
// compare complete path
|
||||||
|
const PlaylistItem* item1 = *(const PlaylistItem**)_item1;
|
||||||
|
const PlaylistItem* item2 = *(const PlaylistItem**)_item2;
|
||||||
|
|
||||||
|
static const size_t bufferSize = 1024;
|
||||||
|
char string1[bufferSize];
|
||||||
|
make_item_compare_string(item1, string1, bufferSize);
|
||||||
|
char string2[bufferSize];
|
||||||
|
make_item_compare_string(item2, string2, bufferSize);
|
||||||
|
|
||||||
|
return strcmp(string1, string2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
Playlist::Playlist()
|
Playlist::Playlist()
|
||||||
: BLocker("playlist lock")
|
:
|
||||||
, fRefs()
|
BLocker("playlist lock"),
|
||||||
, fCurrentIndex(-1)
|
fItems(),
|
||||||
|
fCurrentIndex(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +112,7 @@ Playlist::~Playlist()
|
|||||||
// #pragma mark - archiving
|
// #pragma mark - archiving
|
||||||
|
|
||||||
|
|
||||||
static const char* kPathKey = "path";
|
static const char* kItemArchiveKey = "item";
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
@@ -82,16 +123,22 @@ Playlist::Unarchive(const BMessage* archive)
|
|||||||
|
|
||||||
MakeEmpty();
|
MakeEmpty();
|
||||||
|
|
||||||
BString path;
|
BMessage itemArchive;
|
||||||
for (int32 i = 0; archive->FindString(kPathKey, i, &path) == B_OK; i++) {
|
for (int32 i = 0;
|
||||||
BEntry entry(path.String(), false);
|
archive->FindMessage(kItemArchiveKey, i, &itemArchive) == B_OK; i++) {
|
||||||
// don't follow links, we want to do that when opening files only
|
|
||||||
entry_ref ref;
|
BArchivable* archivable = instantiate_object(&itemArchive);
|
||||||
if (entry.GetRef(&ref) != B_OK)
|
PlaylistItem* item = dynamic_cast<PlaylistItem*>(archivable);
|
||||||
|
if (!item) {
|
||||||
|
delete archivable;
|
||||||
continue;
|
continue;
|
||||||
if (!AddRef(ref))
|
}
|
||||||
|
|
||||||
|
if (!AddItem(item)) {
|
||||||
|
delete item;
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -103,13 +150,14 @@ Playlist::Archive(BMessage* into) const
|
|||||||
if (into == NULL)
|
if (into == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
int32 count = fRefs.CountItems();
|
int32 count = CountItems();
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
const entry_ref* ref = (entry_ref*)fRefs.ItemAtFast(i);
|
const PlaylistItem* item = ItemAtFast(i);
|
||||||
BPath path(ref);
|
BMessage itemArchive;
|
||||||
if (path.InitCheck() != B_OK)
|
status_t ret = item->Archive(&itemArchive);
|
||||||
continue;
|
if (ret != B_OK)
|
||||||
status_t ret = into->AddString(kPathKey, path.Path());
|
return ret;
|
||||||
|
ret = into->AddMessage(kItemArchiveKey, &itemArchive);
|
||||||
if (ret != B_OK)
|
if (ret != B_OK)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -145,7 +193,6 @@ Playlist::Unflatten(BDataIO* stream)
|
|||||||
if (ret != B_OK)
|
if (ret != B_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
return Unarchive(&archive);
|
return Unarchive(&archive);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,54 +224,51 @@ Playlist::Flatten(BDataIO* stream) const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Playlist::MakeEmpty()
|
Playlist::MakeEmpty(bool deleteItems)
|
||||||
{
|
{
|
||||||
int32 count = fRefs.CountItems();
|
int32 count = CountItems();
|
||||||
for (int32 i = count - 1; i >= 0; i--) {
|
for (int32 i = count - 1; i >= 0; i--) {
|
||||||
entry_ref* ref = (entry_ref*)fRefs.RemoveItem(i);
|
PlaylistItem* item = RemoveItem(i, false);
|
||||||
_NotifyRefRemoved(i);
|
_NotifyItemRemoved(i);
|
||||||
delete ref;
|
if (deleteItems)
|
||||||
|
item->RemoveReference();
|
||||||
}
|
}
|
||||||
SetCurrentRefIndex(-1);
|
SetCurrentItemIndex(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
Playlist::CountItems() const
|
Playlist::CountItems() const
|
||||||
{
|
{
|
||||||
return fRefs.CountItems();
|
return fItems.CountItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Playlist::Sort()
|
Playlist::Sort()
|
||||||
{
|
{
|
||||||
fRefs.SortItems(playlist_cmp);
|
fItems.SortItems(playlist_item_compare);
|
||||||
_NotifyRefsSorted();
|
_NotifyItemsSorted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Playlist::AddRef(const entry_ref &ref)
|
Playlist::AddItem(PlaylistItem* item)
|
||||||
{
|
{
|
||||||
return AddRef(ref, CountItems());
|
return AddItem(item, CountItems());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Playlist::AddRef(const entry_ref &ref, int32 index)
|
Playlist::AddItem(PlaylistItem* item, int32 index)
|
||||||
{
|
{
|
||||||
entry_ref* copy = new (nothrow) entry_ref(ref);
|
if (!fItems.AddItem(item, index))
|
||||||
if (!copy)
|
|
||||||
return false;
|
return false;
|
||||||
if (!fRefs.AddItem(copy, index)) {
|
|
||||||
delete copy;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_NotifyRefAdded(ref, index);
|
|
||||||
|
|
||||||
if (index <= fCurrentIndex)
|
if (index <= fCurrentIndex)
|
||||||
SetCurrentRefIndex(fCurrentIndex + 1);
|
SetCurrentItemIndex(fCurrentIndex + 1);
|
||||||
|
|
||||||
|
_NotifyItemAdded(item, index);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -244,85 +288,68 @@ Playlist::AdoptPlaylist(Playlist& other, int32 index)
|
|||||||
return false;
|
return false;
|
||||||
// NOTE: this is not intended to merge two "equal" playlists
|
// NOTE: this is not intended to merge two "equal" playlists
|
||||||
// the given playlist is assumed to be a temporary "dummy"
|
// the given playlist is assumed to be a temporary "dummy"
|
||||||
if (fRefs.AddList(&other.fRefs, index)) {
|
if (fItems.AddList(&other.fItems, index)) {
|
||||||
// take care of the notifications
|
// take care of the notifications
|
||||||
int32 count = other.fRefs.CountItems();
|
int32 count = other.CountItems();
|
||||||
for (int32 i = index; i < index + count; i++) {
|
for (int32 i = index; i < index + count; i++) {
|
||||||
entry_ref* ref = (entry_ref*)fRefs.ItemAtFast(i);
|
PlaylistItem* item = ItemAtFast(i);
|
||||||
_NotifyRefAdded(*ref, i);
|
_NotifyItemAdded(item, i);
|
||||||
}
|
}
|
||||||
if (index <= fCurrentIndex)
|
if (index <= fCurrentIndex)
|
||||||
SetCurrentRefIndex(fCurrentIndex + count);
|
SetCurrentItemIndex(fCurrentIndex + count);
|
||||||
// empty the other list, so that the entry_refs are now ours
|
// empty the other list, so that the PlaylistItems are now ours
|
||||||
other.fRefs.MakeEmpty();
|
other.fItems.MakeEmpty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
entry_ref
|
PlaylistItem*
|
||||||
Playlist::RemoveRef(int32 index, bool careAboutCurrentIndex)
|
Playlist::RemoveItem(int32 index, bool careAboutCurrentIndex)
|
||||||
{
|
{
|
||||||
entry_ref _ref;
|
PlaylistItem* item = (PlaylistItem*)fItems.RemoveItem(index);
|
||||||
entry_ref* ref = (entry_ref*)fRefs.RemoveItem(index);
|
if (!item)
|
||||||
if (!ref)
|
return NULL;
|
||||||
return _ref;
|
_NotifyItemRemoved(index);
|
||||||
_NotifyRefRemoved(index);
|
|
||||||
_ref = *ref;
|
|
||||||
delete ref;
|
|
||||||
|
|
||||||
if (careAboutCurrentIndex) {
|
if (careAboutCurrentIndex) {
|
||||||
if (index == fCurrentIndex)
|
if (index == fCurrentIndex && index >= CountItems())
|
||||||
SetCurrentRefIndex(-1);
|
SetCurrentItemIndex(CountItems() - 1);
|
||||||
else if (index < fCurrentIndex)
|
else if (index < fCurrentIndex)
|
||||||
SetCurrentRefIndex(fCurrentIndex - 1);
|
SetCurrentItemIndex(fCurrentIndex - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _ref;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
Playlist::IndexOf(const entry_ref& _ref) const
|
Playlist::IndexOf(PlaylistItem* item) const
|
||||||
{
|
{
|
||||||
int32 count = CountItems();
|
return fItems.IndexOf(item);
|
||||||
for (int32 i = 0; i < count; i++) {
|
|
||||||
entry_ref* ref = (entry_ref*)fRefs.ItemAtFast(i);
|
|
||||||
if (*ref == _ref)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
PlaylistItem*
|
||||||
Playlist::GetRefAt(int32 index, entry_ref* _ref) const
|
Playlist::ItemAt(int32 index) const
|
||||||
{
|
{
|
||||||
if (!_ref)
|
return (PlaylistItem*)fItems.ItemAt(index);
|
||||||
return B_BAD_VALUE;
|
|
||||||
entry_ref* ref = (entry_ref*)fRefs.ItemAt(index);
|
|
||||||
if (!ref)
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
*_ref = *ref;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//bool
|
PlaylistItem*
|
||||||
//Playlist::HasRef(const entry_ref& ref) const
|
Playlist::ItemAtFast(int32 index) const
|
||||||
//{
|
{
|
||||||
// return IndexOf(ref) >= 0;
|
return (PlaylistItem*)fItems.ItemAtFast(index);
|
||||||
//}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - navigation
|
// #pragma mark - navigation
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Playlist::SetCurrentRefIndex(int32 index)
|
Playlist::SetCurrentItemIndex(int32 index)
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
if (index >= CountItems() || index < 0) {
|
if (index >= CountItems() || index < 0) {
|
||||||
@@ -334,13 +361,13 @@ Playlist::SetCurrentRefIndex(int32 index)
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
fCurrentIndex = index;
|
fCurrentIndex = index;
|
||||||
_NotifyCurrentRefChanged(fCurrentIndex);
|
_NotifyCurrentItemChanged(fCurrentIndex);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
Playlist::CurrentRefIndex() const
|
Playlist::CurrentItemIndex() const
|
||||||
{
|
{
|
||||||
return fCurrentIndex;
|
return fCurrentIndex;
|
||||||
}
|
}
|
||||||
@@ -377,7 +404,7 @@ Playlist::RemoveListener(Listener* listener)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark - support
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -409,7 +436,7 @@ Playlist::AppendRefs(const BMessage* refsReceivedMessage, int32 appendIndex)
|
|||||||
sortPlaylist = false;
|
sortPlaylist = false;
|
||||||
} else {
|
} else {
|
||||||
AppendToPlaylistRecursive(ref, &subPlaylist);
|
AppendToPlaylistRecursive(ref, &subPlaylist);
|
||||||
// At least sort the this subsection of the playlist
|
// At least sort this subsection of the playlist
|
||||||
// if the whole playlist is not sorted anymore.
|
// if the whole playlist is not sorted anymore.
|
||||||
if (!sortPlaylist)
|
if (!sortPlaylist)
|
||||||
subPlaylist.Sort();
|
subPlaylist.Sort();
|
||||||
@@ -426,7 +453,7 @@ Playlist::AppendRefs(const BMessage* refsReceivedMessage, int32 appendIndex)
|
|||||||
|
|
||||||
if (startPlaying) {
|
if (startPlaying) {
|
||||||
// open first file
|
// open first file
|
||||||
SetCurrentRefIndex(0);
|
SetCurrentItemIndex(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,11 +475,11 @@ Playlist::AppendToPlaylistRecursive(const entry_ref& ref, Playlist* playlist)
|
|||||||
while (dir.GetNextRef(&subRef) == B_OK)
|
while (dir.GetNextRef(&subRef) == B_OK)
|
||||||
AppendToPlaylistRecursive(subRef, playlist);
|
AppendToPlaylistRecursive(subRef, playlist);
|
||||||
} else if (entry.IsFile()) {
|
} else if (entry.IsFile()) {
|
||||||
//printf("Is File\n");
|
|
||||||
BString mimeString = _MIMEString(&ref);
|
BString mimeString = _MIMEString(&ref);
|
||||||
if (_IsMediaFile(mimeString)) {
|
if (_IsMediaFile(mimeString)) {
|
||||||
//printf("Adding\n");
|
PlaylistItem* item = new (std::nothrow) FilePlaylistItem(ref);
|
||||||
playlist->AddRef(ref);
|
if (item == NULL || !playlist->AddItem(item))
|
||||||
|
delete item;
|
||||||
} else
|
} else
|
||||||
printf("MIME Type = %s\n", mimeString.String());
|
printf("MIME Type = %s\n", mimeString.String());
|
||||||
}
|
}
|
||||||
@@ -483,7 +510,10 @@ Playlist::AppendPlaylistToPlaylist(const entry_ref& ref, Playlist* playlist)
|
|||||||
printf("Line %s\n", path.Path());
|
printf("Line %s\n", path.Path());
|
||||||
if (path.Path() != NULL) {
|
if (path.Path() != NULL) {
|
||||||
if ((err = get_ref_for_path(path.Path(), &refPath)) == B_OK) {
|
if ((err = get_ref_for_path(path.Path(), &refPath)) == B_OK) {
|
||||||
playlist->AddRef(refPath);
|
PlaylistItem* item
|
||||||
|
= new (std::nothrow) FilePlaylistItem(refPath);
|
||||||
|
if (item == NULL || !playlist->AddItem(item))
|
||||||
|
delete item;
|
||||||
} else
|
} else
|
||||||
printf("Error - %s: [%lx]\n", strerror(err), (int32) err);
|
printf("Error - %s: [%lx]\n", strerror(err), (int32) err);
|
||||||
} else
|
} else
|
||||||
@@ -498,21 +528,7 @@ Playlist::AppendPlaylistToPlaylist(const entry_ref& ref, Playlist* playlist)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark - private
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
Playlist::playlist_cmp(const void *p1, const void *p2)
|
|
||||||
{
|
|
||||||
// compare complete path
|
|
||||||
BEntry a(*(const entry_ref **)p1, false);
|
|
||||||
BEntry b(*(const entry_ref **)p2, false);
|
|
||||||
|
|
||||||
BPath aPath(&a);
|
|
||||||
BPath bPath(&b);
|
|
||||||
|
|
||||||
return strcmp(aPath.Path(), bPath.Path());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*static*/ bool
|
/*static*/ bool
|
||||||
@@ -524,10 +540,29 @@ Playlist::_IsMediaFile(const BString& mimeString)
|
|||||||
if (fileType.GetSupertype(&superType) != B_OK)
|
if (fileType.GetSupertype(&superType) != B_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TODO: some media files have other super types, I think
|
// try a shortcut first
|
||||||
// for example ASF has "application" super type... so it would
|
if (superType == "audio" || superType == "video")
|
||||||
// need special handling
|
return true;
|
||||||
return (superType == "audio" || superType == "video");
|
|
||||||
|
// Look through our supported types
|
||||||
|
app_info appInfo;
|
||||||
|
if (be_app->GetAppInfo(&appInfo) != B_OK)
|
||||||
|
return false;
|
||||||
|
BFile appFile(&appInfo.ref, B_READ_ONLY);
|
||||||
|
if (appFile.InitCheck() != B_OK)
|
||||||
|
return false;
|
||||||
|
BMessage types;
|
||||||
|
BAppFileInfo appFileInfo(&appFile);
|
||||||
|
if (appFileInfo.GetSupportedTypes(&types) != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char* type;
|
||||||
|
for (int32 i = 0; types.FindString("types", i, &type) == B_OK; i++) {
|
||||||
|
if (strcasecmp(mimeString.String(), type) == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -570,50 +605,53 @@ Playlist::_MIMEString(const entry_ref* ref)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - notifications
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Playlist::_NotifyRefAdded(const entry_ref& ref, int32 index) const
|
Playlist::_NotifyItemAdded(PlaylistItem* item, int32 index) const
|
||||||
{
|
{
|
||||||
BList listeners(fListeners);
|
BList listeners(fListeners);
|
||||||
int32 count = listeners.CountItems();
|
int32 count = listeners.CountItems();
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
||||||
listener->RefAdded(ref, index);
|
listener->ItemAdded(item, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Playlist::_NotifyRefRemoved(int32 index) const
|
Playlist::_NotifyItemRemoved(int32 index) const
|
||||||
{
|
{
|
||||||
BList listeners(fListeners);
|
BList listeners(fListeners);
|
||||||
int32 count = listeners.CountItems();
|
int32 count = listeners.CountItems();
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
||||||
listener->RefRemoved(index);
|
listener->ItemRemoved(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Playlist::_NotifyRefsSorted() const
|
Playlist::_NotifyItemsSorted() const
|
||||||
{
|
{
|
||||||
BList listeners(fListeners);
|
BList listeners(fListeners);
|
||||||
int32 count = listeners.CountItems();
|
int32 count = listeners.CountItems();
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
||||||
listener->RefsSorted();
|
listener->ItemsSorted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Playlist::_NotifyCurrentRefChanged(int32 newIndex) const
|
Playlist::_NotifyCurrentItemChanged(int32 newIndex) const
|
||||||
{
|
{
|
||||||
BList listeners(fListeners);
|
BList listeners(fListeners);
|
||||||
int32 count = listeners.CountItems();
|
int32 count = listeners.CountItems();
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
||||||
listener->CurrentRefChanged(newIndex);
|
listener->CurrentItemChanged(newIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Playlist.h - Media Player for the Haiku Operating System
|
* Playlist.h - Media Player for the Haiku Operating System
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
||||||
* Copyright (C) 2007 Stephan Aßmus <superstippi@gmx.de>
|
* Copyright (C) 2007-2009 Stephan Aßmus <superstippi@gmx.de> (MIT ok)
|
||||||
* Copyright (C) 2008-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok)
|
* Copyright (C) 2008-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@@ -22,13 +22,15 @@
|
|||||||
#ifndef __PLAYLIST_H
|
#ifndef __PLAYLIST_H
|
||||||
#define __PLAYLIST_H
|
#define __PLAYLIST_H
|
||||||
|
|
||||||
#include <Entry.h>
|
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
|
|
||||||
|
#include "PlaylistItem.h"
|
||||||
|
|
||||||
class BDataIO;
|
class BDataIO;
|
||||||
class BMessage;
|
class BMessage;
|
||||||
class BString;
|
class BString;
|
||||||
|
struct entry_ref;
|
||||||
|
|
||||||
|
|
||||||
class Playlist : public BLocker {
|
class Playlist : public BLocker {
|
||||||
@@ -38,12 +40,12 @@ public:
|
|||||||
Listener();
|
Listener();
|
||||||
virtual ~Listener();
|
virtual ~Listener();
|
||||||
|
|
||||||
virtual void RefAdded(const entry_ref& ref, int32 index);
|
virtual void ItemAdded(PlaylistItem* item, int32 index);
|
||||||
virtual void RefRemoved(int32 index);
|
virtual void ItemRemoved(int32 index);
|
||||||
|
|
||||||
virtual void RefsSorted();
|
virtual void ItemsSorted();
|
||||||
|
|
||||||
virtual void CurrentRefChanged(int32 newIndex);
|
virtual void CurrentItemChanged(int32 newIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -58,26 +60,26 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
// list functionality
|
// list functionality
|
||||||
void MakeEmpty();
|
void MakeEmpty(bool deleteItems = true);
|
||||||
int32 CountItems() const;
|
int32 CountItems() const;
|
||||||
|
|
||||||
void Sort();
|
void Sort();
|
||||||
|
|
||||||
bool AddRef(const entry_ref& ref);
|
bool AddItem(PlaylistItem* item);
|
||||||
bool AddRef(const entry_ref& ref, int32 index);
|
bool AddItem(PlaylistItem* item, int32 index);
|
||||||
entry_ref RemoveRef(int32 index,
|
PlaylistItem* RemoveItem(int32 index,
|
||||||
bool careAboutCurrentIndex = true);
|
bool careAboutCurrentIndex = true);
|
||||||
|
|
||||||
bool AdoptPlaylist(Playlist& other);
|
bool AdoptPlaylist(Playlist& other);
|
||||||
bool AdoptPlaylist(Playlist& other, int32 index);
|
bool AdoptPlaylist(Playlist& other, int32 index);
|
||||||
|
|
||||||
int32 IndexOf(const entry_ref& ref) const;
|
int32 IndexOf(PlaylistItem* item) const;
|
||||||
status_t GetRefAt(int32 index, entry_ref* ref) const;
|
PlaylistItem* ItemAt(int32 index) const;
|
||||||
// bool HasRef(const entry_ref& ref) const;
|
PlaylistItem* ItemAtFast(int32 index) const;
|
||||||
|
|
||||||
// navigating current ref
|
// navigating current ref
|
||||||
bool SetCurrentRefIndex(int32 index);
|
bool SetCurrentItemIndex(int32 index);
|
||||||
int32 CurrentRefIndex() const;
|
int32 CurrentItemIndex() const;
|
||||||
|
|
||||||
void GetSkipInfo(bool* canSkipPrevious,
|
void GetSkipInfo(bool* canSkipPrevious,
|
||||||
bool* canSkipNext) const;
|
bool* canSkipNext) const;
|
||||||
@@ -95,20 +97,20 @@ public:
|
|||||||
Playlist* playlist);
|
Playlist* playlist);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int playlist_cmp(const void* p1, const void* p2);
|
|
||||||
static bool _IsMediaFile(const BString& mimeString);
|
static bool _IsMediaFile(const BString& mimeString);
|
||||||
static bool _IsTextPlaylist(const BString& mimeString);
|
static bool _IsTextPlaylist(const BString& mimeString);
|
||||||
static bool _IsBinaryPlaylist(const BString& mimeString);
|
static bool _IsBinaryPlaylist(const BString& mimeString);
|
||||||
static bool _IsPlaylist(const BString& mimeString);
|
static bool _IsPlaylist(const BString& mimeString);
|
||||||
static BString _MIMEString(const entry_ref* ref);
|
static BString _MIMEString(const entry_ref* ref);
|
||||||
void _NotifyRefAdded(const entry_ref& ref,
|
|
||||||
|
void _NotifyItemAdded(PlaylistItem*,
|
||||||
int32 index) const;
|
int32 index) const;
|
||||||
void _NotifyRefRemoved(int32 index) const;
|
void _NotifyItemRemoved(int32 index) const;
|
||||||
void _NotifyRefsSorted() const;
|
void _NotifyItemsSorted() const;
|
||||||
void _NotifyCurrentRefChanged(int32 newIndex) const;
|
void _NotifyCurrentItemChanged(int32 newIndex) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BList fRefs;
|
BList fItems;
|
||||||
BList fListeners;
|
BList fListeners;
|
||||||
|
|
||||||
int32 fCurrentIndex;
|
int32 fCurrentIndex;
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "PlaylistItem.h"
|
#include "PlaylistItem.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
PlaylistItem::Listener::Listener()
|
PlaylistItem::Listener::Listener()
|
||||||
{
|
{
|
||||||
@@ -22,13 +24,97 @@ void PlaylistItem::Listener::ItemChanged(const PlaylistItem* item)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
//#define DEBUG_INSTANCE_COUNT
|
||||||
|
#ifdef DEBUG_INSTANCE_COUNT
|
||||||
|
static vint32 sInstanceCount = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
PlaylistItem::PlaylistItem()
|
PlaylistItem::PlaylistItem()
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_INSTANCE_COUNT
|
||||||
|
atomic_add(&sInstanceCount, 1);
|
||||||
|
printf("%p->PlaylistItem::PlaylistItem() (%ld)\n", this, sInstanceCount);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PlaylistItem::~PlaylistItem()
|
PlaylistItem::~PlaylistItem()
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_INSTANCE_COUNT
|
||||||
|
atomic_add(&sInstanceCount, -1);
|
||||||
|
printf("%p->PlaylistItem::~PlaylistItem() (%ld)\n", this, sInstanceCount);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
PlaylistItem::Name() const
|
||||||
|
{
|
||||||
|
BString name;
|
||||||
|
if (GetAttribute(ATTR_STRING_NAME, name) != B_OK)
|
||||||
|
name = "<unnamed>";
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
PlaylistItem::Author() const
|
||||||
|
{
|
||||||
|
BString author;
|
||||||
|
if (GetAttribute(ATTR_STRING_AUTHOR, author) != B_OK)
|
||||||
|
author = "<unknown>";
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
PlaylistItem::Album() const
|
||||||
|
{
|
||||||
|
BString album;
|
||||||
|
if (GetAttribute(ATTR_STRING_ALBUM, album) != B_OK)
|
||||||
|
album = "<unknown>";
|
||||||
|
return album;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
PlaylistItem::Title() const
|
||||||
|
{
|
||||||
|
BString title;
|
||||||
|
if (GetAttribute(ATTR_STRING_TITLE, title) != B_OK)
|
||||||
|
title = "<untitled>";
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PlaylistItem::TrackNumber() const
|
||||||
|
{
|
||||||
|
int32 trackNumber;
|
||||||
|
if (GetAttribute(ATTR_INT32_TRACK, trackNumber) != B_OK)
|
||||||
|
trackNumber = 0;
|
||||||
|
return trackNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PlaylistItem::BitRate() const
|
||||||
|
{
|
||||||
|
int32 bitrate;
|
||||||
|
if (GetAttribute(ATTR_INT32_BIT_RATE, bitrate) != B_OK)
|
||||||
|
bitrate = 0;
|
||||||
|
return bitrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
PlaylistItem::Duration() const
|
||||||
|
{
|
||||||
|
bigtime_t duration;
|
||||||
|
if (GetAttribute(ATTR_INT64_DURATION, duration) != B_OK)
|
||||||
|
duration = 0;
|
||||||
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,18 @@
|
|||||||
#ifndef PLAYLIST_ITEM_H
|
#ifndef PLAYLIST_ITEM_H
|
||||||
#define PLAYLIST_ITEM_H
|
#define PLAYLIST_ITEM_H
|
||||||
|
|
||||||
|
#include <Archivable.h>
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
#include <Referenceable.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
class BBitmap;
|
||||||
class BDataIO;
|
class BDataIO;
|
||||||
class BMediaFile;
|
class BMediaFile;
|
||||||
class BMessage;
|
class BMessage;
|
||||||
|
|
||||||
class PlaylistItem {
|
class PlaylistItem : public BArchivable, public Referenceable {
|
||||||
public:
|
public:
|
||||||
class Listener {
|
class Listener {
|
||||||
public:
|
public:
|
||||||
@@ -26,35 +30,60 @@ public:
|
|||||||
PlaylistItem();
|
PlaylistItem();
|
||||||
virtual ~PlaylistItem();
|
virtual ~PlaylistItem();
|
||||||
|
|
||||||
|
virtual PlaylistItem* Clone() const = 0;
|
||||||
|
|
||||||
// archiving
|
// archiving
|
||||||
// virtual status_t Unarchive(const BMessage* archive) = 0;
|
virtual status_t Archive(BMessage* into,
|
||||||
// virtual status_t Archive(BMessage* into) const = 0;
|
bool deep = true) const = 0;
|
||||||
//
|
|
||||||
// virtual status_t Unflatten(BDataIO* stream) = 0;
|
|
||||||
// virtual status_t Flatten(BDataIO* stream) const = 0;
|
|
||||||
|
|
||||||
// properties
|
// attributes
|
||||||
virtual status_t SetName(const BString& name) = 0;
|
typedef enum {
|
||||||
virtual status_t GetName(BString& name) const = 0;
|
ATTR_STRING_NAME = 'name',
|
||||||
|
ATTR_STRING_KEYWORDS = 'kwrd',
|
||||||
|
|
||||||
virtual status_t SetTitle(const BString& title) = 0;
|
ATTR_STRING_AUTHOR = 'auth',
|
||||||
virtual status_t GetTitle(BString& title) const = 0;
|
ATTR_STRING_ALBUM = 'albm',
|
||||||
|
ATTR_STRING_TITLE = 'titl',
|
||||||
|
|
||||||
virtual status_t SetAuthor(const BString& author) = 0;
|
ATTR_INT32_TRACK = 'trck',
|
||||||
virtual status_t GetAuthor(BString& author) const = 0;
|
ATTR_INT32_YEAR = 'year',
|
||||||
|
ATTR_INT32_RATING = 'rtng',
|
||||||
|
ATTR_INT32_BIT_RATE = 'btrt',
|
||||||
|
|
||||||
virtual status_t SetAlbum(const BString& album) = 0;
|
ATTR_INT64_DURATION = 'drtn'
|
||||||
virtual status_t GetAlbum(BString& album) const = 0;
|
} Attribute;
|
||||||
|
|
||||||
virtual status_t SetTrackNumber(int32 trackNumber) = 0;
|
virtual status_t SetAttribute(const Attribute& attribute,
|
||||||
virtual status_t GetTrackNumber(int32& trackNumber) const = 0;
|
const BString& string) = 0;
|
||||||
|
virtual status_t GetAttribute(const Attribute& attribute,
|
||||||
|
BString& string) const = 0;
|
||||||
|
|
||||||
virtual status_t SetBitRate(int32 bitRate) = 0;
|
virtual status_t SetAttribute(const Attribute& attribute,
|
||||||
virtual status_t GetBitRate(int32& bitRate) const = 0;
|
const int32& value) = 0;
|
||||||
|
virtual status_t GetAttribute(const Attribute& attribute,
|
||||||
|
int32& value) const = 0;
|
||||||
|
|
||||||
virtual status_t GetDuration(bigtime_t& duration) const = 0;
|
virtual status_t SetAttribute(const Attribute& attribute,
|
||||||
|
const int64& value) = 0;
|
||||||
|
virtual status_t GetAttribute(const Attribute& attribute,
|
||||||
|
int64& value) const = 0;
|
||||||
|
|
||||||
|
// convenience access to attributes
|
||||||
|
BString Name() const;
|
||||||
|
BString Author() const;
|
||||||
|
BString Album() const;
|
||||||
|
BString Title() const;
|
||||||
|
|
||||||
|
int32 TrackNumber() const;
|
||||||
|
int32 BitRate() const;
|
||||||
|
|
||||||
|
bigtime_t Duration() const;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
virtual BString LocationURI() const = 0;
|
||||||
|
virtual status_t GetIcon(BBitmap* bitmap,
|
||||||
|
icon_size iconSize) const = 0;
|
||||||
|
|
||||||
virtual status_t MoveIntoTrash() = 0;
|
virtual status_t MoveIntoTrash() = 0;
|
||||||
virtual status_t RestoreFromTrash() = 0;
|
virtual status_t RestoreFromTrash() = 0;
|
||||||
|
|
||||||
@@ -72,4 +101,6 @@ private:
|
|||||||
BList fListeners;
|
BList fListeners;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef Reference<PlaylistItem> PlaylistItemRef;
|
||||||
|
|
||||||
#endif // PLAYLIST_ITEM_H
|
#endif // PLAYLIST_ITEM_H
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007-2009, Haiku. All rights reserved.
|
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PlaylistListView.h"
|
#include "PlaylistListView.h"
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
@@ -29,6 +27,7 @@
|
|||||||
#include "MovePLItemsCommand.h"
|
#include "MovePLItemsCommand.h"
|
||||||
#include "PlaybackState.h"
|
#include "PlaybackState.h"
|
||||||
#include "Playlist.h"
|
#include "Playlist.h"
|
||||||
|
#include "PlaylistItem.h"
|
||||||
#include "PlaylistObserver.h"
|
#include "PlaylistObserver.h"
|
||||||
#include "RandomizePLItemsCommand.h"
|
#include "RandomizePLItemsCommand.h"
|
||||||
#include "RemovePLItemsCommand.h"
|
#include "RemovePLItemsCommand.h"
|
||||||
@@ -56,9 +55,10 @@ text_offset(const font_height& fh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PlaylistListView::Item : public SimpleItem {
|
class PlaylistListView::Item : public SimpleItem,
|
||||||
|
public PlaylistItem::Listener {
|
||||||
public:
|
public:
|
||||||
Item(const entry_ref& ref);
|
Item(PlaylistItem* item);
|
||||||
virtual ~Item();
|
virtual ~Item();
|
||||||
|
|
||||||
void Draw(BView* owner, BRect frame,
|
void Draw(BView* owner, BRect frame,
|
||||||
@@ -67,21 +67,25 @@ class PlaylistListView::Item : public SimpleItem {
|
|||||||
bool active,
|
bool active,
|
||||||
uint32 playbackState);
|
uint32 playbackState);
|
||||||
|
|
||||||
|
virtual void ItemChanged(const PlaylistItem* item);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
entry_ref fRef;
|
PlaylistItemRef fItem;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PlaylistListView::Item::Item(const entry_ref& ref)
|
PlaylistListView::Item::Item(PlaylistItem* item)
|
||||||
: SimpleItem(ref.name),
|
: SimpleItem(item->Name().String()),
|
||||||
fRef(ref)
|
fItem(item)
|
||||||
{
|
{
|
||||||
|
fItem->AddListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PlaylistListView::Item::~Item()
|
PlaylistListView::Item::~Item()
|
||||||
{
|
{
|
||||||
|
fItem->RemoveListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -202,6 +206,13 @@ PlaylistListView::Item::Draw(BView* owner, BRect frame, const font_height& fh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaylistListView::Item::ItemChanged(const PlaylistItem* item)
|
||||||
|
{
|
||||||
|
// TODO: Invalidate
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -234,6 +245,8 @@ PlaylistListView::PlaylistListView(BRect frame, Playlist* playlist,
|
|||||||
|
|
||||||
PlaylistListView::~PlaylistListView()
|
PlaylistListView::~PlaylistListView()
|
||||||
{
|
{
|
||||||
|
for (int32 i = CountItems() - 1; i >= 0; i--)
|
||||||
|
_RemoveItem(i);
|
||||||
fPlaylist->RemoveListener(fPlaylistObserver);
|
fPlaylist->RemoveListener(fPlaylistObserver);
|
||||||
delete fPlaylistObserver;
|
delete fPlaylistObserver;
|
||||||
fController->RemoveListener(fControllerObserver);
|
fController->RemoveListener(fControllerObserver);
|
||||||
@@ -258,24 +271,27 @@ PlaylistListView::MessageReceived(BMessage* message)
|
|||||||
// message->PrintToStream();
|
// message->PrintToStream();
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
// PlaylistObserver messages
|
// PlaylistObserver messages
|
||||||
case MSG_PLAYLIST_REF_ADDED: {
|
case MSG_PLAYLIST_ITEM_ADDED:
|
||||||
entry_ref ref;
|
{
|
||||||
|
PlaylistItem* item;
|
||||||
int32 index;
|
int32 index;
|
||||||
if (message->FindRef("refs", &ref) == B_OK
|
if (message->FindPointer("item", (void**)&item) == B_OK
|
||||||
&& message->FindInt32("index", &index) == B_OK)
|
&& message->FindInt32("index", &index) == B_OK)
|
||||||
_AddItem(ref, index);
|
_AddItem(item, index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_PLAYLIST_REF_REMOVED: {
|
case MSG_PLAYLIST_ITEM_REMOVED:
|
||||||
|
{
|
||||||
int32 index;
|
int32 index;
|
||||||
if (message->FindInt32("index", &index) == B_OK)
|
if (message->FindInt32("index", &index) == B_OK)
|
||||||
_RemoveItem(index);
|
_RemoveItem(index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_PLAYLIST_REFS_SORTED:
|
case MSG_PLAYLIST_ITEMS_SORTED:
|
||||||
_FullSync();
|
_FullSync();
|
||||||
break;
|
break;
|
||||||
case MSG_PLAYLIST_CURRENT_REF_CHANGED: {
|
case MSG_PLAYLIST_CURRENT_ITEM_CHANGED:
|
||||||
|
{
|
||||||
int32 index;
|
int32 index;
|
||||||
if (message->FindInt32("index", &index) == B_OK)
|
if (message->FindInt32("index", &index) == B_OK)
|
||||||
_SetCurrentPlaylistIndex(index);
|
_SetCurrentPlaylistIndex(index);
|
||||||
@@ -283,7 +299,8 @@ PlaylistListView::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ControllerObserver messages
|
// ControllerObserver messages
|
||||||
case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED: {
|
case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED:
|
||||||
|
{
|
||||||
uint32 state;
|
uint32 state;
|
||||||
if (message->FindInt32("state", (int32*)&state) == B_OK)
|
if (message->FindInt32("state", (int32*)&state) == B_OK)
|
||||||
_SetPlaybackState(state);
|
_SetPlaybackState(state);
|
||||||
@@ -330,7 +347,7 @@ PlaylistListView::MouseDown(BPoint where)
|
|||||||
// only do something if user clicked the same item twice
|
// only do something if user clicked the same item twice
|
||||||
if (fLastClickedItem == item) {
|
if (fLastClickedItem == item) {
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
fPlaylist->SetCurrentRefIndex(i);
|
fPlaylist->SetCurrentItemIndex(i);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -486,16 +503,14 @@ PlaylistListView::_FullSync()
|
|||||||
scrollBar->SetTarget((BView*)NULL);
|
scrollBar->SetTarget((BView*)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
MakeEmpty();
|
for (int32 i = CountItems() - 1; i >= 0; i--)
|
||||||
|
_RemoveItem(i);
|
||||||
|
|
||||||
int32 count = fPlaylist->CountItems();
|
int32 count = fPlaylist->CountItems();
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++)
|
||||||
entry_ref ref;
|
_AddItem(fPlaylist->ItemAt(i), i);
|
||||||
if (fPlaylist->GetRefAt(i, &ref) == B_OK)
|
|
||||||
_AddItem(ref, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
_SetCurrentPlaylistIndex(fPlaylist->CurrentRefIndex());
|
_SetCurrentPlaylistIndex(fPlaylist->CurrentItemIndex());
|
||||||
_SetPlaybackState(fController->PlaybackState());
|
_SetPlaybackState(fController->PlaybackState());
|
||||||
|
|
||||||
// reattach scrollbar and sync it by calling FrameResized()
|
// reattach scrollbar and sync it by calling FrameResized()
|
||||||
@@ -509,10 +524,13 @@ PlaylistListView::_FullSync()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PlaylistListView::_AddItem(const entry_ref& ref, int32 index)
|
PlaylistListView::_AddItem(PlaylistItem* _item, int32 index)
|
||||||
{
|
{
|
||||||
Item* item = new (nothrow) Item(ref);
|
if (_item == NULL)
|
||||||
if (item)
|
return;
|
||||||
|
|
||||||
|
Item* item = new (nothrow) Item(_item);
|
||||||
|
if (item != NULL)
|
||||||
AddItem(item, index);
|
AddItem(item, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class CommandStack;
|
|||||||
class Controller;
|
class Controller;
|
||||||
class ControllerObserver;
|
class ControllerObserver;
|
||||||
class Playlist;
|
class Playlist;
|
||||||
|
class PlaylistItem;
|
||||||
class PlaylistObserver;
|
class PlaylistObserver;
|
||||||
|
|
||||||
class PlaylistListView : public SimpleListView {
|
class PlaylistListView : public SimpleListView {
|
||||||
@@ -53,7 +54,7 @@ private:
|
|||||||
class Item;
|
class Item;
|
||||||
|
|
||||||
void _FullSync();
|
void _FullSync();
|
||||||
void _AddItem(const entry_ref& ref, int32 index);
|
void _AddItem(PlaylistItem* item, int32 index);
|
||||||
void _RemoveItem(int32 index);
|
void _RemoveItem(int32 index);
|
||||||
|
|
||||||
void _SetCurrentPlaylistIndex(int32 index);
|
void _SetCurrentPlaylistIndex(int32 index);
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Haiku. All rights reserved.
|
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PlaylistObserver.h"
|
#include "PlaylistObserver.h"
|
||||||
@@ -24,10 +21,10 @@ PlaylistObserver::~PlaylistObserver()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PlaylistObserver::RefAdded(const entry_ref& ref, int32 index)
|
PlaylistObserver::ItemAdded(PlaylistItem* item, int32 index)
|
||||||
{
|
{
|
||||||
BMessage message(MSG_PLAYLIST_REF_ADDED);
|
BMessage message(MSG_PLAYLIST_ITEM_ADDED);
|
||||||
message.AddRef("refs", &ref);
|
message.AddPointer("item", item);
|
||||||
message.AddInt32("index", index);
|
message.AddInt32("index", index);
|
||||||
|
|
||||||
DeliverMessage(message);
|
DeliverMessage(message);
|
||||||
@@ -35,9 +32,9 @@ PlaylistObserver::RefAdded(const entry_ref& ref, int32 index)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PlaylistObserver::RefRemoved(int32 index)
|
PlaylistObserver::ItemRemoved(int32 index)
|
||||||
{
|
{
|
||||||
BMessage message(MSG_PLAYLIST_REF_REMOVED);
|
BMessage message(MSG_PLAYLIST_ITEM_REMOVED);
|
||||||
message.AddInt32("index", index);
|
message.AddInt32("index", index);
|
||||||
|
|
||||||
DeliverMessage(message);
|
DeliverMessage(message);
|
||||||
@@ -45,18 +42,18 @@ PlaylistObserver::RefRemoved(int32 index)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PlaylistObserver::RefsSorted()
|
PlaylistObserver::ItemsSorted()
|
||||||
{
|
{
|
||||||
BMessage message(MSG_PLAYLIST_REFS_SORTED);
|
BMessage message(MSG_PLAYLIST_ITEMS_SORTED);
|
||||||
|
|
||||||
DeliverMessage(message);
|
DeliverMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PlaylistObserver::CurrentRefChanged(int32 newIndex)
|
PlaylistObserver::CurrentItemChanged(int32 newIndex)
|
||||||
{
|
{
|
||||||
BMessage message(MSG_PLAYLIST_CURRENT_REF_CHANGED);
|
BMessage message(MSG_PLAYLIST_CURRENT_ITEM_CHANGED);
|
||||||
message.AddInt32("index", newIndex);
|
message.AddInt32("index", newIndex);
|
||||||
|
|
||||||
DeliverMessage(message);
|
DeliverMessage(message);
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Haiku. All rights reserved.
|
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
#ifndef PLAYLIST_OBSERVER_H
|
#ifndef PLAYLIST_OBSERVER_H
|
||||||
#define PLAYLIST_OBSERVER_H
|
#define PLAYLIST_OBSERVER_H
|
||||||
@@ -12,24 +9,23 @@
|
|||||||
#include "Playlist.h"
|
#include "Playlist.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MSG_PLAYLIST_REF_ADDED = 'plra',
|
MSG_PLAYLIST_ITEM_ADDED = 'plia',
|
||||||
MSG_PLAYLIST_REF_REMOVED = 'plrr',
|
MSG_PLAYLIST_ITEM_REMOVED = 'plir',
|
||||||
MSG_PLAYLIST_REFS_SORTED = 'plrs',
|
MSG_PLAYLIST_ITEMS_SORTED = 'plis',
|
||||||
MSG_PLAYLIST_CURRENT_REF_CHANGED = 'plcc'
|
MSG_PLAYLIST_CURRENT_ITEM_CHANGED = 'plcc'
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlaylistObserver : public Playlist::Listener,
|
class PlaylistObserver : public Playlist::Listener, public AbstractLOAdapter {
|
||||||
public AbstractLOAdapter {
|
|
||||||
public:
|
public:
|
||||||
PlaylistObserver(BHandler* target);
|
PlaylistObserver(BHandler* target);
|
||||||
virtual ~PlaylistObserver();
|
virtual ~PlaylistObserver();
|
||||||
|
|
||||||
virtual void RefAdded(const entry_ref& ref, int32 index);
|
virtual void ItemAdded(PlaylistItem* item, int32 index);
|
||||||
virtual void RefRemoved(int32 index);
|
virtual void ItemRemoved(int32 index);
|
||||||
|
|
||||||
virtual void RefsSorted();
|
virtual void ItemsSorted();
|
||||||
|
|
||||||
virtual void CurrentRefChanged(int32 newIndex);
|
virtual void CurrentItemChanged(int32 newIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PLAYLIST_OBSERVER_H
|
#endif // PLAYLIST_OBSERVER_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2008 Stephan Aßmus. All rights reserved.
|
* Copyright © 2008-2009 Stephan Aßmus <superstippi@gmx.de>
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "RandomizePLItemsCommand.h"
|
#include "RandomizePLItemsCommand.h"
|
||||||
@@ -19,31 +19,33 @@ using std::nothrow;
|
|||||||
|
|
||||||
RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
|
RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
|
||||||
const int32* indices, int32 count)
|
const int32* indices, int32 count)
|
||||||
: Command()
|
:
|
||||||
, fPlaylist(playlist)
|
PLItemsCommand(),
|
||||||
, fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL)
|
fPlaylist(playlist),
|
||||||
, fListIndices(count > 0 ? new (nothrow) int32[count] : NULL)
|
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
|
||||||
, fRandomInternalIndices(count > 0 ? new (nothrow) int32[count] : NULL)
|
fListIndices(count > 0 ? new (nothrow) int32[count] : NULL),
|
||||||
, fCount(count)
|
fRandomInternalIndices(count > 0 ? new (nothrow) int32[count] : NULL),
|
||||||
|
fCount(count)
|
||||||
{
|
{
|
||||||
if (!indices || !fPlaylist || !fRefs || !fListIndices
|
if (!indices || !fPlaylist || !fItems || !fListIndices
|
||||||
|| !fRandomInternalIndices) {
|
|| !fRandomInternalIndices) {
|
||||||
// indicate a bad object state
|
// indicate a bad object state
|
||||||
delete[] fRefs;
|
delete[] fItems;
|
||||||
fRefs = NULL;
|
fItems = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(fListIndices, indices, fCount * sizeof(int32));
|
memcpy(fListIndices, indices, fCount * sizeof(int32));
|
||||||
|
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++) {
|
||||||
if (fPlaylist->GetRefAt(fListIndices[i], &fRefs[i]) < B_OK
|
fItems[i] = fPlaylist->ItemAt(fListIndices[i]);
|
||||||
|| !indexSet.AddItem((void*)i)) {
|
if (fItems[i] == NULL || !indexSet.AddItem((void*)i)) {
|
||||||
// indicate a bad object state
|
// indicate a bad object state
|
||||||
delete[] fRefs;
|
delete[] fItems;
|
||||||
fRefs = NULL;
|
fItems = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,7 +60,7 @@ RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
|
|||||||
|
|
||||||
RandomizePLItemsCommand::~RandomizePLItemsCommand()
|
RandomizePLItemsCommand::~RandomizePLItemsCommand()
|
||||||
{
|
{
|
||||||
delete[] fRefs;
|
delete[] fItems;
|
||||||
delete[] fListIndices;
|
delete[] fListIndices;
|
||||||
delete[] fRandomInternalIndices;
|
delete[] fRandomInternalIndices;
|
||||||
}
|
}
|
||||||
@@ -67,7 +69,7 @@ RandomizePLItemsCommand::~RandomizePLItemsCommand()
|
|||||||
status_t
|
status_t
|
||||||
RandomizePLItemsCommand::InitCheck()
|
RandomizePLItemsCommand::InitCheck()
|
||||||
{
|
{
|
||||||
if (!fRefs)
|
if (!fItems)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -100,36 +102,34 @@ RandomizePLItemsCommand::_Sort(bool random)
|
|||||||
{
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
// remember currently playling ref in case we move it
|
// remember currently playling item in case we move it
|
||||||
entry_ref currentRef;
|
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
|
||||||
¤tRef) == B_OK;
|
|
||||||
|
|
||||||
// remove refs from playlist
|
// remove refs from playlist
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
// "- i" to account for the items already removed
|
// "- i" to account for the items already removed
|
||||||
fPlaylist->RemoveRef(fListIndices[i] - i, false);
|
fPlaylist->RemoveItem(fListIndices[i] - i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add refs to playlist at the randomized indices
|
// add refs to playlist at the randomized indices
|
||||||
if (random) {
|
if (random) {
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
if (!fPlaylist->AddRef(fRefs[fRandomInternalIndices[i]],
|
if (!fPlaylist->AddItem(fItems[fRandomInternalIndices[i]],
|
||||||
fListIndices[i])) {
|
fListIndices[i])) {
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
if (!fPlaylist->AddRef(fRefs[i], fListIndices[i])) {
|
if (!fPlaylist->AddItem(fItems[i], fListIndices[i])) {
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// take care about currently played ref
|
// take care about currently played item
|
||||||
if (adjustCurrentRef)
|
if (current != NULL)
|
||||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2008 Stephan Aßmus. All rights reserved.
|
* Copyright © 2008-2009 Stephan Aßmus <superstippi@gmx.de>
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef RANDOMIZE_PL_ITEMS_COMMAND_H
|
#ifndef RANDOMIZE_PL_ITEMS_COMMAND_H
|
||||||
#define RANDOMIZE_PL_ITEMS_COMMAND_H
|
#define RANDOMIZE_PL_ITEMS_COMMAND_H
|
||||||
|
|
||||||
|
|
||||||
#include "Command.h"
|
#include "PLItemsCommand.h"
|
||||||
|
|
||||||
class Playlist;
|
class RandomizePLItemsCommand : public PLItemsCommand {
|
||||||
struct entry_ref;
|
|
||||||
|
|
||||||
class RandomizePLItemsCommand : public Command {
|
|
||||||
public:
|
public:
|
||||||
RandomizePLItemsCommand(
|
RandomizePLItemsCommand(
|
||||||
Playlist* playlist,
|
Playlist* playlist,
|
||||||
@@ -30,7 +27,7 @@ class RandomizePLItemsCommand : public Command {
|
|||||||
status_t _Sort(bool random);
|
status_t _Sort(bool random);
|
||||||
|
|
||||||
Playlist* fPlaylist;
|
Playlist* fPlaylist;
|
||||||
entry_ref* fRefs;
|
PlaylistItem** fItems;
|
||||||
int32* fListIndices;
|
int32* fListIndices;
|
||||||
int32* fRandomInternalIndices;
|
int32* fRandomInternalIndices;
|
||||||
int32 fCount;
|
int32 fCount;
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007-2009, Haiku. All rights reserved.
|
* Copyright © 2007-2009 Stephan Aßmus <superstippi@gmx.de>
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "RemovePLItemsCommand.h"
|
#include "RemovePLItemsCommand.h"
|
||||||
@@ -13,10 +10,6 @@
|
|||||||
|
|
||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
#include <Directory.h>
|
|
||||||
#include <Entry.h>
|
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <Path.h>
|
|
||||||
|
|
||||||
#include "Playlist.h"
|
#include "Playlist.h"
|
||||||
|
|
||||||
@@ -27,35 +20,31 @@ using std::nothrow;
|
|||||||
RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist,
|
RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist,
|
||||||
const int32* indices, int32 count, bool moveFilesToTrash)
|
const int32* indices, int32 count, bool moveFilesToTrash)
|
||||||
:
|
:
|
||||||
Command(),
|
PLItemsCommand(),
|
||||||
fPlaylist(playlist),
|
fPlaylist(playlist),
|
||||||
fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL),
|
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
|
||||||
fNamesInTrash(NULL),
|
|
||||||
fIndices(count > 0 ? new (nothrow) int32[count] : NULL),
|
fIndices(count > 0 ? new (nothrow) int32[count] : NULL),
|
||||||
fCount(count),
|
fCount(count),
|
||||||
fMoveFilesToTrash(moveFilesToTrash),
|
fMoveFilesToTrash(moveFilesToTrash),
|
||||||
fMoveErrorShown(false)
|
fMoveErrorShown(false),
|
||||||
|
fItemsRemoved(false)
|
||||||
{
|
{
|
||||||
if (!indices || !fPlaylist || !fRefs || !fIndices) {
|
if (!indices || !fPlaylist || !fItems || !fIndices) {
|
||||||
// indicate a bad object state
|
// indicate a bad object state
|
||||||
delete[] fRefs;
|
delete[] fItems;
|
||||||
fRefs = NULL;
|
fItems = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(fIndices, indices, fCount * sizeof(int32));
|
memcpy(fIndices, indices, fCount * sizeof(int32));
|
||||||
|
memset(fItems, 0, fCount * sizeof(PlaylistItem*));
|
||||||
if (fMoveFilesToTrash) {
|
|
||||||
fNamesInTrash = new (nothrow) BString[count];
|
|
||||||
if (fNamesInTrash == NULL)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init original entry indices
|
// init original entry indices
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
if (fPlaylist->GetRefAt(fIndices[i], &fRefs[i]) < B_OK) {
|
fItems[i] = fPlaylist->ItemAt(fIndices[i]);
|
||||||
delete[] fRefs;
|
if (fItems[i] == NULL) {
|
||||||
fRefs = NULL;
|
delete[] fItems;
|
||||||
|
fItems = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,19 +53,16 @@ RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist,
|
|||||||
|
|
||||||
RemovePLItemsCommand::~RemovePLItemsCommand()
|
RemovePLItemsCommand::~RemovePLItemsCommand()
|
||||||
{
|
{
|
||||||
delete[] fRefs;
|
_CleanUp(fItems, fCount, fItemsRemoved);
|
||||||
delete[] fIndices;
|
delete[] fIndices;
|
||||||
delete[] fNamesInTrash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
RemovePLItemsCommand::InitCheck()
|
RemovePLItemsCommand::InitCheck()
|
||||||
{
|
{
|
||||||
if (!fPlaylist || !fRefs || !fIndices
|
if (!fPlaylist || !fItems || !fIndices)
|
||||||
|| (fMoveFilesToTrash && !fNamesInTrash)) {
|
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
}
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,65 +72,32 @@ RemovePLItemsCommand::Perform()
|
|||||||
{
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
|
fItemsRemoved = true;
|
||||||
|
|
||||||
int32 lastRemovedIndex = -1;
|
int32 lastRemovedIndex = -1;
|
||||||
|
|
||||||
// remove refs from playlist
|
// remove refs from playlist
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
// "- i" to account for the items already removed
|
// "- i" to account for the items already removed
|
||||||
lastRemovedIndex = fIndices[i] - i;
|
lastRemovedIndex = fIndices[i] - i;
|
||||||
fPlaylist->RemoveRef(lastRemovedIndex);
|
fPlaylist->RemoveItem(lastRemovedIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// in case we removed the currently playing file
|
// in case we removed the currently playing file
|
||||||
if (fPlaylist->CurrentRefIndex() == -1)
|
if (fPlaylist->CurrentItemIndex() == -1)
|
||||||
fPlaylist->SetCurrentRefIndex(lastRemovedIndex);
|
fPlaylist->SetCurrentItemIndex(lastRemovedIndex);
|
||||||
|
|
||||||
if (fMoveFilesToTrash) {
|
if (fMoveFilesToTrash) {
|
||||||
BString errorFiles;
|
BString errorFiles;
|
||||||
status_t moveError = B_OK;
|
status_t moveError = B_OK;
|
||||||
bool errorOnAllFiles = true;
|
bool errorOnAllFiles = true;
|
||||||
char trashPath[B_PATH_NAME_LENGTH];
|
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
status_t err = find_directory(B_TRASH_DIRECTORY, fRefs[i].device,
|
status_t err = fItems[i]->MoveIntoTrash();
|
||||||
true /*create it*/, trashPath, B_PATH_NAME_LENGTH);
|
|
||||||
if (err != B_OK) {
|
|
||||||
fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
BEntry entry(&fRefs[i]);
|
|
||||||
err = entry.InitCheck();
|
|
||||||
if (err != B_OK) {
|
|
||||||
fprintf(stderr, "failed to init BEntry for %s: %s\n",
|
|
||||||
fRefs[i].name, strerror(err));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
BDirectory trashDir(trashPath);
|
|
||||||
if (err != B_OK) {
|
|
||||||
fprintf(stderr, "failed to init BDirectory for %s: %s\n",
|
|
||||||
trashPath, strerror(err));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a unique name for the entry in the trash
|
|
||||||
fNamesInTrash[i] = fRefs[i].name;
|
|
||||||
int32 uniqueNameIndex = 1;
|
|
||||||
while (true) {
|
|
||||||
BEntry test(&trashDir, fNamesInTrash[i].String());
|
|
||||||
if (!test.Exists())
|
|
||||||
break;
|
|
||||||
fNamesInTrash[i] = fRefs[i].name;
|
|
||||||
fNamesInTrash[i] << ' ' << uniqueNameIndex;
|
|
||||||
uniqueNameIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, move the entry into the trash
|
|
||||||
err = entry.MoveTo(&trashDir, fNamesInTrash[i].String());
|
|
||||||
if (err != B_OK) {
|
if (err != B_OK) {
|
||||||
moveError = err;
|
moveError = err;
|
||||||
if (errorFiles.Length() > 0)
|
if (errorFiles.Length() > 0)
|
||||||
errorFiles << ' ';
|
errorFiles << ' ';
|
||||||
errorFiles << fRefs[i].name;
|
errorFiles << fItems[i]->Name();
|
||||||
} else
|
} else
|
||||||
errorOnAllFiles = false;
|
errorOnAllFiles = false;
|
||||||
}
|
}
|
||||||
@@ -173,61 +126,21 @@ RemovePLItemsCommand::Undo()
|
|||||||
{
|
{
|
||||||
BAutolock _(fPlaylist);
|
BAutolock _(fPlaylist);
|
||||||
|
|
||||||
status_t ret = B_OK;
|
fItemsRemoved = false;
|
||||||
|
|
||||||
if (fMoveFilesToTrash) {
|
if (fMoveFilesToTrash) {
|
||||||
char trashPath[B_PATH_NAME_LENGTH];
|
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
status_t err = find_directory(B_TRASH_DIRECTORY, fRefs[i].device,
|
fItems[i]->RestoreFromTrash();
|
||||||
false /*create it*/, trashPath, B_PATH_NAME_LENGTH);
|
|
||||||
if (err != B_OK) {
|
|
||||||
fprintf(stderr, "failed to find Trash: %s\n", strerror(err));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// construct the entry to the file in the trash
|
|
||||||
// TODO: BEntry(const BDirectory* directory, const char* path) is broken!
|
|
||||||
// BEntry entry(trashPath, fNamesInTrash[i].String());
|
|
||||||
BPath path(trashPath, fNamesInTrash[i].String());
|
|
||||||
BEntry entry(path.Path());
|
|
||||||
err = entry.InitCheck();
|
|
||||||
if (err != B_OK) {
|
|
||||||
fprintf(stderr, "failed to init BEntry for %s: %s\n",
|
|
||||||
fNamesInTrash[i].String(), strerror(err));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//entry.GetPath(&path);
|
|
||||||
//printf("moving '%s'\n", path.Path());
|
|
||||||
|
|
||||||
// construct the folder of the original entry_ref
|
|
||||||
node_ref nodeRef;
|
|
||||||
nodeRef.device = fRefs[i].device;
|
|
||||||
nodeRef.node = fRefs[i].directory;
|
|
||||||
BDirectory originalDir(&nodeRef);
|
|
||||||
|
|
||||||
if (err != B_OK) {
|
|
||||||
fprintf(stderr, "failed to init original BDirectory for "
|
|
||||||
"%s: %s\n", fRefs[i].name, strerror(err));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//path.SetTo(&originalDir, fRefs[i].name);
|
|
||||||
//printf("as '%s'\n", path.Path());
|
|
||||||
|
|
||||||
// Finally, move the entry back into the original folder
|
|
||||||
err = entry.MoveTo(&originalDir, fRefs[i].name);
|
|
||||||
if (err != B_OK)
|
|
||||||
ret = err;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remember currently playling ref in case we move it
|
// remember currently playling item in case we move it
|
||||||
entry_ref currentRef;
|
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
|
||||||
¤tRef) == B_OK;
|
|
||||||
|
|
||||||
// add refs to playlist at remembered indices
|
// add items to playlist at remembered indices
|
||||||
|
status_t ret = B_OK;
|
||||||
for (int32 i = 0; i < fCount; i++) {
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
if (!fPlaylist->AddRef(fRefs[i], fIndices[i])) {
|
if (!fPlaylist->AddItem(fItems[i], fIndices[i])) {
|
||||||
ret = B_NO_MEMORY;
|
ret = B_NO_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -236,8 +149,8 @@ BEntry entry(path.Path());
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
// take care about currently played ref
|
// take care about currently played ref
|
||||||
if (adjustCurrentRef)
|
if (current != NULL)
|
||||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007-2009, Haiku. All rights reserved.
|
* Copyright © 2007-2009 Stephan Aßmus <superstippi@gmx.de>
|
||||||
* Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus <superstippi@gmx.de>
|
|
||||||
*/
|
*/
|
||||||
#ifndef REMOVE_PL_ITEMS_COMMAND_H
|
#ifndef REMOVE_PL_ITEMS_COMMAND_H
|
||||||
#define REMOVE_PL_ITEMS_COMMAND_H
|
#define REMOVE_PL_ITEMS_COMMAND_H
|
||||||
|
|
||||||
|
|
||||||
#include "Command.h"
|
#include "PLItemsCommand.h"
|
||||||
|
|
||||||
struct entry_ref;
|
class RemovePLItemsCommand : public PLItemsCommand {
|
||||||
class Playlist;
|
|
||||||
|
|
||||||
class RemovePLItemsCommand : public Command {
|
|
||||||
public:
|
public:
|
||||||
RemovePLItemsCommand(
|
RemovePLItemsCommand(
|
||||||
Playlist* playlist,
|
Playlist* playlist,
|
||||||
@@ -32,12 +26,12 @@ class RemovePLItemsCommand : public Command {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Playlist* fPlaylist;
|
Playlist* fPlaylist;
|
||||||
entry_ref* fRefs;
|
PlaylistItem** fItems;
|
||||||
BString* fNamesInTrash;
|
|
||||||
int32* fIndices;
|
int32* fIndices;
|
||||||
int32 fCount;
|
int32 fCount;
|
||||||
bool fMoveFilesToTrash;
|
bool fMoveFilesToTrash;
|
||||||
bool fMoveErrorShown;
|
bool fMoveErrorShown;
|
||||||
|
bool fItemsRemoved;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // REMOVE_PL_ITEMS_COMMAND_H
|
#endif // REMOVE_PL_ITEMS_COMMAND_H
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ using namespace std;
|
|||||||
|
|
||||||
//#define TRACE_AUDIO_SUPPLIER
|
//#define TRACE_AUDIO_SUPPLIER
|
||||||
#ifdef TRACE_AUDIO_SUPPLIER
|
#ifdef TRACE_AUDIO_SUPPLIER
|
||||||
# define TRACE(x...) printf("MediaTrackAudioSupplier::"); printf(x)
|
# define TRACE(x...) printf("MediaTrackAudioSupplier::" x)
|
||||||
#else
|
#else
|
||||||
# define TRACE(x...)
|
# define TRACE(x...)
|
||||||
#endif
|
#endif
|
||||||
@@ -123,6 +123,8 @@ MediaTrackAudioSupplier::Read(void* buffer, int64 pos, int64 frames)
|
|||||||
frames);
|
frames);
|
||||||
TRACE(" this: %p, fOutOffset: %lld\n", this, fOutOffset);
|
TRACE(" this: %p, fOutOffset: %lld\n", this, fOutOffset);
|
||||||
|
|
||||||
|
//printf("MediaTrackAudioSupplier::Read(%p, %lld, %lld)\n", buffer, pos, frames);
|
||||||
|
|
||||||
status_t error = InitCheck();
|
status_t error = InitCheck();
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
TRACE("Read() done\n");
|
TRACE("Read() done\n");
|
||||||
@@ -141,6 +143,58 @@ MediaTrackAudioSupplier::Read(void* buffer, int64 pos, int64 frames)
|
|||||||
TRACE(" after eliminating the frames after the track end: %p, %lld, %lld\n",
|
TRACE(" after eliminating the frames after the track end: %p, %lld, %lld\n",
|
||||||
buffer, pos, frames);
|
buffer, pos, frames);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
const media_format& format = Format();
|
||||||
|
int64 size = format.u.raw_audio.buffer_size;
|
||||||
|
uint32 bytesPerFrame = format.u.raw_audio.channel_count
|
||||||
|
* (format.u.raw_audio.format
|
||||||
|
& media_raw_audio_format::B_AUDIO_SIZE_MASK);
|
||||||
|
uint32 framesPerBuffer = size / bytesPerFrame;
|
||||||
|
|
||||||
|
if (fMediaTrack->CurrentFrame() != pos) {
|
||||||
|
printf(" needing to seek: %lld (%lld)\n", pos,
|
||||||
|
fMediaTrack->CurrentFrame());
|
||||||
|
|
||||||
|
int64 keyFrame = pos;
|
||||||
|
error = fMediaTrack->FindKeyFrameForFrame(&keyFrame,
|
||||||
|
B_MEDIA_SEEK_CLOSEST_BACKWARD);
|
||||||
|
if (error == B_OK) {
|
||||||
|
error = fMediaTrack->SeekToFrame(&keyFrame,
|
||||||
|
B_MEDIA_SEEK_CLOSEST_BACKWARD);
|
||||||
|
}
|
||||||
|
if (error != B_OK) {
|
||||||
|
printf(" error seeking to position: %lld (%lld)\n", pos,
|
||||||
|
fMediaTrack->CurrentFrame());
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyFrame < pos) {
|
||||||
|
printf(" need to skip %lld frames\n", pos - keyFrame);
|
||||||
|
uint8 dummyBuffer[size];
|
||||||
|
while (pos - keyFrame >= framesPerBuffer) {
|
||||||
|
printf(" skipped %lu frames (full buffer)\n", framesPerBuffer);
|
||||||
|
int64 sizeToRead = size;
|
||||||
|
fMediaTrack->ReadFrames(dummyBuffer, &sizeToRead);
|
||||||
|
keyFrame += framesPerBuffer;
|
||||||
|
}
|
||||||
|
int64 restSize = pos - keyFrame;
|
||||||
|
if (restSize > 0) {
|
||||||
|
printf(" skipped %lu frames (rest)\n", framesPerBuffer);
|
||||||
|
fMediaTrack->ReadFrames(dummyBuffer, &restSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (frames > 0) {
|
||||||
|
printf(" reading %lu frames (full buffer)\n", framesPerBuffer);
|
||||||
|
int64 sizeToRead = min_c(size, frames * bytesPerFrame);
|
||||||
|
fMediaTrack->ReadFrames(buffer, &sizeToRead);
|
||||||
|
buffer = (uint8*)buffer + sizeToRead;
|
||||||
|
frames -= framesPerBuffer;
|
||||||
|
}
|
||||||
|
printf(" done\n\n");
|
||||||
|
|
||||||
|
#else
|
||||||
// read the cached frames
|
// read the cached frames
|
||||||
bigtime_t time = system_time();
|
bigtime_t time = system_time();
|
||||||
if (frames > 0)
|
if (frames > 0)
|
||||||
@@ -152,6 +206,7 @@ MediaTrackAudioSupplier::Read(void* buffer, int64 pos, int64 frames)
|
|||||||
if (frames > 0)
|
if (frames > 0)
|
||||||
_ReadUncachedFrames(buffer, pos, frames, time);
|
_ReadUncachedFrames(buffer, pos, frames, time);
|
||||||
|
|
||||||
|
#endif
|
||||||
TRACE("Read() done\n");
|
TRACE("Read() done\n");
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -203,6 +258,8 @@ MediaTrackAudioSupplier::_InitFromTrack()
|
|||||||
|
|
||||||
TRACE("MediaTrackAudioSupplier: keyframes: %d, frame count: %lld\n",
|
TRACE("MediaTrackAudioSupplier: keyframes: %d, frame count: %lld\n",
|
||||||
fHasKeyFrames, fCountFrames);
|
fHasKeyFrames, fCountFrames);
|
||||||
|
printf("MediaTrackAudioSupplier: keyframes: %d, frame count: %lld\n",
|
||||||
|
fHasKeyFrames, fCountFrames);
|
||||||
} else
|
} else
|
||||||
fMediaTrack = NULL;
|
fMediaTrack = NULL;
|
||||||
}
|
}
|
||||||
@@ -416,19 +473,6 @@ MediaTrackAudioSupplier::_ReadBuffer(Buffer* buffer, int64 position,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _ReadCachedFrames
|
|
||||||
//
|
|
||||||
// Tries to read as much as possible data from the cache. The supplied
|
|
||||||
// buffer pointer as well as position and number of frames are adjusted
|
|
||||||
// accordingly. The used cache buffers are stamped with the current
|
|
||||||
// system time.
|
|
||||||
void
|
|
||||||
MediaTrackAudioSupplier::_ReadCachedFrames(void*& dest, int64& pos,
|
|
||||||
int64& frames)
|
|
||||||
{
|
|
||||||
_ReadCachedFrames(dest, pos, frames, system_time());
|
|
||||||
}
|
|
||||||
|
|
||||||
// _ReadCachedFrames
|
// _ReadCachedFrames
|
||||||
//
|
//
|
||||||
// Tries to read as much as possible data from the cache. The supplied
|
// Tries to read as much as possible data from the cache. The supplied
|
||||||
@@ -454,9 +498,9 @@ MediaTrackAudioSupplier::_ReadCachedFrames(void*& dest, int64& pos,
|
|||||||
pos += size;
|
pos += size;
|
||||||
frames -= size;
|
frames -= size;
|
||||||
dest = SkipFrames(dest, size);
|
dest = SkipFrames(dest, size);
|
||||||
}
|
|
||||||
buffer->time_stamp = time;
|
buffer->time_stamp = time;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Step backward through the list of cache buffers and try to read as
|
// Step backward through the list of cache buffers and try to read as
|
||||||
// much data from the end as possible.
|
// much data from the end as possible.
|
||||||
for (int32 i = buffers.CountItems() - 1;
|
for (int32 i = buffers.CountItems() - 1;
|
||||||
@@ -469,23 +513,11 @@ MediaTrackAudioSupplier::_ReadCachedFrames(void*& dest, int64& pos,
|
|||||||
_CopyFrames(buffer->data, buffer->offset, dest, pos,
|
_CopyFrames(buffer->data, buffer->offset, dest, pos,
|
||||||
pos + frames - size, size);
|
pos + frames - size, size);
|
||||||
frames -= size;
|
frames -= size;
|
||||||
|
buffer->time_stamp = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// _ReadUncachedFrames
|
|
||||||
//
|
|
||||||
// Reads /frames/ frames from /position/ into /buffer/. The frames are not
|
|
||||||
// read from the cache, but read frames are cached, if possible.
|
|
||||||
// New cache buffers are stamped with the system time.
|
|
||||||
// If an error occurs, the untouched part of the buffer is set to 0.
|
|
||||||
status_t
|
|
||||||
MediaTrackAudioSupplier::_ReadUncachedFrames(void* buffer, int64 position,
|
|
||||||
int64 frames)
|
|
||||||
{
|
|
||||||
return _ReadUncachedFrames(buffer, position, frames, system_time());
|
|
||||||
}
|
|
||||||
|
|
||||||
// _ReadUncachedFrames
|
// _ReadUncachedFrames
|
||||||
//
|
//
|
||||||
// Reads /frames/ frames from /position/ into /buffer/. The frames are not
|
// Reads /frames/ frames from /position/ into /buffer/. The frames are not
|
||||||
@@ -521,8 +553,10 @@ MediaTrackAudioSupplier::_ReadUncachedFrames(void* buffer, int64 position,
|
|||||||
currentPos += cacheBuffer->size;
|
currentPos += cacheBuffer->size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
// Ensure that all frames up to the next key frame are cached.
|
// Ensure that all frames up to the next key frame are cached.
|
||||||
// This avoids, that each read
|
// This avoids, that each read reaches the BMediaTrack.
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
int64 nextKeyFrame = currentPos;
|
int64 nextKeyFrame = currentPos;
|
||||||
if (_FindKeyFrameForward(nextKeyFrame) == B_OK) {
|
if (_FindKeyFrameForward(nextKeyFrame) == B_OK) {
|
||||||
@@ -540,6 +574,8 @@ MediaTrackAudioSupplier::_ReadUncachedFrames(void* buffer, int64 position,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// on error fill up the buffer with silence
|
// on error fill up the buffer with silence
|
||||||
if (error != B_OK && frames > 0)
|
if (error != B_OK && frames > 0)
|
||||||
ReadSilence(buffer, frames);
|
ReadSilence(buffer, frames);
|
||||||
@@ -551,17 +587,17 @@ status_t
|
|||||||
MediaTrackAudioSupplier::_FindKeyFrameForward(int64& position)
|
MediaTrackAudioSupplier::_FindKeyFrameForward(int64& position)
|
||||||
{
|
{
|
||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
// NOTE: the keyframe version confuses the Frauenhofer MP3 decoder,
|
#ifdef __HAIKU__
|
||||||
// it works fine with the non-keyframe version, so let's hope this
|
if (fHasKeyFrames) {
|
||||||
// is the case for all other keyframe based BeOS codecs...
|
error = fMediaTrack->FindKeyFrameForFrame(
|
||||||
// if (fHasKeyFrames) {
|
&position, B_MEDIA_SEEK_CLOSEST_FORWARD);
|
||||||
// error = fMediaTrack->FindKeyFrameForFrame(
|
} else
|
||||||
// &position, B_MEDIA_SEEK_CLOSEST_FORWARD);
|
#endif
|
||||||
// } else {
|
{
|
||||||
int64 framesPerBuffer = _FramesPerBuffer();
|
int64 framesPerBuffer = _FramesPerBuffer();
|
||||||
position += framesPerBuffer - 1;
|
position += framesPerBuffer - 1;
|
||||||
position = position % framesPerBuffer;
|
position = position % framesPerBuffer;
|
||||||
// }
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,6 +614,7 @@ MediaTrackAudioSupplier::_FindKeyFrameBackward(int64& position)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
// _SeekToKeyFrameForward
|
// _SeekToKeyFrameForward
|
||||||
status_t
|
status_t
|
||||||
MediaTrackAudioSupplier::_SeekToKeyFrameForward(int64& position)
|
MediaTrackAudioSupplier::_SeekToKeyFrameForward(int64& position)
|
||||||
@@ -601,6 +638,7 @@ MediaTrackAudioSupplier::_SeekToKeyFrameForward(int64& position)
|
|||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// _SeekToKeyFrameBackward
|
// _SeekToKeyFrameBackward
|
||||||
status_t
|
status_t
|
||||||
@@ -614,16 +652,16 @@ MediaTrackAudioSupplier::_SeekToKeyFrameBackward(int64& position)
|
|||||||
int64 oldPosition = position;
|
int64 oldPosition = position;
|
||||||
error = fMediaTrack->FindKeyFrameForFrame(&position,
|
error = fMediaTrack->FindKeyFrameForFrame(&position,
|
||||||
B_MEDIA_SEEK_CLOSEST_BACKWARD);
|
B_MEDIA_SEEK_CLOSEST_BACKWARD);
|
||||||
if (error >= B_OK)
|
if (error == B_OK)
|
||||||
error = fMediaTrack->SeekToFrame(&position, 0);
|
error = fMediaTrack->SeekToFrame(&position, 0);
|
||||||
if (error < B_OK) {
|
if (error != B_OK) {
|
||||||
position = fMediaTrack->CurrentFrame();
|
position = fMediaTrack->CurrentFrame();
|
||||||
if (fReportSeekError) {
|
// if (fReportSeekError) {
|
||||||
printf(" seek to key frame backward: %lld -> %lld (%lld) "
|
printf(" seek to key frame backward: %lld -> %lld (%lld) "
|
||||||
"- %s\n", oldPosition, position,
|
"- %s\n", oldPosition, position,
|
||||||
fMediaTrack->CurrentFrame(), strerror(error));
|
fMediaTrack->CurrentFrame(), strerror(error));
|
||||||
fReportSeekError = false;
|
fReportSeekError = false;
|
||||||
}
|
// }
|
||||||
} else {
|
} else {
|
||||||
fReportSeekError = true;
|
fReportSeekError = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,21 +62,18 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier {
|
|||||||
status_t _ReadBuffer(Buffer* buffer, int64 position,
|
status_t _ReadBuffer(Buffer* buffer, int64 position,
|
||||||
bigtime_t time);
|
bigtime_t time);
|
||||||
|
|
||||||
void _ReadCachedFrames(void*& buffer,
|
|
||||||
int64& position, int64& frames);
|
|
||||||
void _ReadCachedFrames(void*& buffer,
|
void _ReadCachedFrames(void*& buffer,
|
||||||
int64& position, int64& frames,
|
int64& position, int64& frames,
|
||||||
bigtime_t time);
|
bigtime_t time);
|
||||||
|
|
||||||
status_t _ReadUncachedFrames(void* buffer,
|
|
||||||
int64 position, int64 frames);
|
|
||||||
status_t _ReadUncachedFrames(void* buffer,
|
status_t _ReadUncachedFrames(void* buffer,
|
||||||
int64 position, int64 frames,
|
int64 position, int64 frames,
|
||||||
bigtime_t time);
|
bigtime_t time);
|
||||||
|
|
||||||
status_t _FindKeyFrameForward(int64& position);
|
status_t _FindKeyFrameForward(int64& position);
|
||||||
status_t _FindKeyFrameBackward(int64& position);
|
status_t _FindKeyFrameBackward(int64& position);
|
||||||
status_t _SeekToKeyFrameForward(int64& position);
|
// NOTE: unused
|
||||||
|
// status_t _SeekToKeyFrameForward(int64& position);
|
||||||
status_t _SeekToKeyFrameBackward(int64& position);
|
status_t _SeekToKeyFrameBackward(int64& position);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user