* 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:
parent
a428058ded
commit
c60fcc87e0
@ -51,10 +51,10 @@
|
||||
using std::nothrow;
|
||||
|
||||
|
||||
void
|
||||
void
|
||||
HandleError(const char *text, status_t err)
|
||||
{
|
||||
if (err != B_OK) {
|
||||
if (err != B_OK) {
|
||||
printf("%s. error 0x%08x (%s)\n",text, (int)err, strerror(err));
|
||||
fflush(NULL);
|
||||
exit(1);
|
||||
@ -91,7 +91,7 @@ Controller::Controller()
|
||||
// but use only if there are multiple players running at all!
|
||||
fMuted(false),
|
||||
|
||||
fRef(),
|
||||
fItem(NULL),
|
||||
fMediaFile(NULL),
|
||||
|
||||
fVideoSupplier(new ProxyVideoSupplier()),
|
||||
@ -185,11 +185,11 @@ Controller::CreateAudioSupplier()
|
||||
|
||||
|
||||
status_t
|
||||
Controller::SetTo(const entry_ref &ref)
|
||||
Controller::SetTo(const PlaylistItemRef& item)
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
if (fRef == ref) {
|
||||
if (fItem == item) {
|
||||
if (InitCheck() == B_OK) {
|
||||
if (fAutoplay) {
|
||||
SetPosition(0.0);
|
||||
@ -199,14 +199,14 @@ Controller::SetTo(const entry_ref &ref)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
fRef = ref;
|
||||
fItem = item;
|
||||
|
||||
fAudioSupplier->SetSupplier(NULL, fVideoFrameRate);
|
||||
fVideoSupplier->SetSupplier(NULL);
|
||||
|
||||
fAudioTrackList.MakeEmpty();
|
||||
fVideoTrackList.MakeEmpty();
|
||||
|
||||
|
||||
ObjectDeleter<BMediaFile> oldMediaFileDeleter(fMediaFile);
|
||||
// BMediaFile destructor will call ReleaseAllTracks()
|
||||
fMediaFile = NULL;
|
||||
@ -224,25 +224,26 @@ Controller::SetTo(const entry_ref &ref)
|
||||
fDuration = 0;
|
||||
fVideoFrameRate = 25.0;
|
||||
|
||||
status_t err;
|
||||
|
||||
BMediaFile* mf = new BMediaFile(&ref);
|
||||
if (fItem.Get() == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
BMediaFile* mf = fItem->CreateMediaFile();
|
||||
ObjectDeleter<BMediaFile> mediaFileDeleter(mf);
|
||||
|
||||
err = mf->InitCheck();
|
||||
status_t err = mf->InitCheck();
|
||||
if (err != B_OK) {
|
||||
printf("Controller::SetTo: initcheck failed\n");
|
||||
_NotifyFileChanged();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int trackcount = mf->CountTracks();
|
||||
if (trackcount <= 0) {
|
||||
printf("Controller::SetTo: trackcount %d\n", trackcount);
|
||||
_NotifyFileChanged();
|
||||
return B_MEDIA_NO_HANDLER;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < trackcount; i++) {
|
||||
BMediaTrack* t = mf->TrackAt(i);
|
||||
media_format f;
|
||||
@ -253,13 +254,13 @@ Controller::SetTo(const entry_ref &ref)
|
||||
mf->ReleaseTrack(t);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (t->Duration() <= 0) {
|
||||
printf("Controller::SetTo: track index %d has no duration\n",i);
|
||||
mf->ReleaseTrack(t);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (f.IsAudio()) {
|
||||
if (!fAudioTrackList.AddItem(t))
|
||||
return B_NO_MEMORY;
|
||||
@ -395,7 +396,7 @@ Controller::VideoTrackCount()
|
||||
|
||||
status_t
|
||||
Controller::SelectAudioTrack(int n)
|
||||
{
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
BMediaTrack* track = (BMediaTrack *)fAudioTrackList.ItemAt(n);
|
||||
@ -503,7 +504,7 @@ Controller::Play()
|
||||
//printf("Controller::Play\n");
|
||||
|
||||
BAutolock _(this);
|
||||
|
||||
|
||||
StartPlaying();
|
||||
fAutoplay = true;
|
||||
}
|
||||
@ -602,7 +603,7 @@ Controller::VolumeDown()
|
||||
|
||||
void
|
||||
Controller::ToggleMute()
|
||||
{
|
||||
{
|
||||
if (!Lock())
|
||||
return;
|
||||
|
||||
@ -624,7 +625,7 @@ Controller::Volume()
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
return fVolume;
|
||||
return fVolume;
|
||||
}
|
||||
|
||||
|
||||
@ -679,14 +680,9 @@ status_t
|
||||
Controller::GetLocation(BString* location)
|
||||
{
|
||||
// you need to hold the data lock
|
||||
if (!fMediaFile)
|
||||
if (fItem.Get() == NULL)
|
||||
return B_NO_INIT;
|
||||
BPath path(&fRef);
|
||||
status_t ret = path.InitCheck();
|
||||
if (ret < B_OK)
|
||||
return ret;
|
||||
*location = "";
|
||||
*location << "file://" << path.Path();
|
||||
*location = fItem->LocationURI();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -695,9 +691,9 @@ status_t
|
||||
Controller::GetName(BString* name)
|
||||
{
|
||||
// you need to hold the data lock
|
||||
if (!fMediaFile)
|
||||
if (fItem.Get() == NULL)
|
||||
return B_NO_INIT;
|
||||
*name = fRef.name;
|
||||
*name = fItem->Name();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,13 @@
|
||||
|
||||
#include "ListenerAdapter.h"
|
||||
#include "NodeManager.h"
|
||||
#include "PlaylistItem.h"
|
||||
|
||||
class AudioTrackSupplier;
|
||||
class BBitmap;
|
||||
class BMediaFile;
|
||||
class BMediaTrack;
|
||||
class PlaylistItem;
|
||||
class ProxyAudioSupplier;
|
||||
class ProxyVideoSupplier;
|
||||
class SoundOutput;
|
||||
@ -78,16 +80,16 @@ public:
|
||||
virtual AudioSupplier* CreateAudioSupplier();
|
||||
|
||||
// Controller
|
||||
status_t SetTo(const entry_ref &ref);
|
||||
entry_ref Ref() const
|
||||
{ return fRef; }
|
||||
status_t SetTo(const PlaylistItemRef& item);
|
||||
const PlaylistItem* Item() const
|
||||
{ return fItem.Get(); }
|
||||
void PlayerActivated(bool active);
|
||||
|
||||
void GetSize(int *width, int *height);
|
||||
|
||||
int AudioTrackCount();
|
||||
int VideoTrackCount();
|
||||
|
||||
|
||||
status_t SelectAudioTrack(int n);
|
||||
int CurrentAudioTrack();
|
||||
status_t SelectVideoTrack(int n);
|
||||
@ -123,7 +125,7 @@ public:
|
||||
|
||||
// video view
|
||||
void SetVideoView(VideoView *view);
|
||||
|
||||
|
||||
bool IsOverlayActive();
|
||||
|
||||
// notification support
|
||||
@ -148,7 +150,7 @@ private:
|
||||
void _NotifyVolumeChanged(float volume) const;
|
||||
void _NotifyMutedChanged(bool muted) const;
|
||||
|
||||
// overridden from PlaybackManager so that we
|
||||
// overridden from PlaybackManager so that we
|
||||
// can use our own Listener mechanism
|
||||
virtual void NotifyPlayModeChanged(int32 mode) const;
|
||||
virtual void NotifyLoopModeChanged(int32 mode) const;
|
||||
@ -167,7 +169,7 @@ private:
|
||||
float fActiveVolume;
|
||||
bool fMuted;
|
||||
|
||||
entry_ref fRef;
|
||||
PlaylistItemRef fItem;
|
||||
BMediaFile* fMediaFile;
|
||||
|
||||
ProxyVideoSupplier* fVideoSupplier;
|
||||
@ -194,7 +196,7 @@ private:
|
||||
bool fLoopMovies;
|
||||
bool fLoopSounds;
|
||||
uint32 fBackgroundMovieVolumeMode;
|
||||
|
||||
|
||||
BList fListeners;
|
||||
};
|
||||
|
||||
|
@ -63,18 +63,18 @@ ControllerView::Draw(BRect updateRect)
|
||||
|
||||
|
||||
void
|
||||
ControllerView::MessageReceived(BMessage *msg)
|
||||
ControllerView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case MSG_PLAYLIST_REF_ADDED:
|
||||
case MSG_PLAYLIST_REF_REMOVED:
|
||||
case MSG_PLAYLIST_REFS_SORTED:
|
||||
case MSG_PLAYLIST_CURRENT_REF_CHANGED:
|
||||
switch (message->what) {
|
||||
case MSG_PLAYLIST_ITEM_ADDED:
|
||||
case MSG_PLAYLIST_ITEM_REMOVED:
|
||||
case MSG_PLAYLIST_ITEMS_SORTED:
|
||||
case MSG_PLAYLIST_CURRENT_ITEM_CHANGED:
|
||||
_CheckSkippable();
|
||||
break;
|
||||
|
||||
default:
|
||||
TransportControlGroup::MessageReceived(msg);
|
||||
TransportControlGroup::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ void
|
||||
ControllerView::SkipBackward()
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() - 1);
|
||||
fPlaylist->SetCurrentItemIndex(fPlaylist->CurrentItemIndex() - 1);
|
||||
}
|
||||
|
||||
|
||||
@ -131,7 +131,7 @@ void
|
||||
ControllerView::SkipForward()
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1);
|
||||
fPlaylist->SetCurrentItemIndex(fPlaylist->CurrentItemIndex() + 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include "Controller.h"
|
||||
#include "ControllerObserver.h"
|
||||
#include "PlaylistItem.h"
|
||||
|
||||
|
||||
#define NAME "File Info"
|
||||
@ -55,7 +56,7 @@ public:
|
||||
virtual ~InfoView();
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
status_t SetIcon(const entry_ref& ref);
|
||||
status_t SetIcon(const PlaylistItem* item);
|
||||
status_t SetIcon(const char* mimeType);
|
||||
void SetGenericIcon();
|
||||
|
||||
@ -71,7 +72,7 @@ InfoView::InfoView(BRect frame, const char *name, float divider)
|
||||
fIconBitmap(NULL)
|
||||
{
|
||||
BRect rect(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1);
|
||||
|
||||
|
||||
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
||||
fIconBitmap = new BBitmap(rect, B_RGBA32);
|
||||
#else
|
||||
@ -106,11 +107,9 @@ InfoView::Draw(BRect updateRect)
|
||||
|
||||
|
||||
status_t
|
||||
InfoView::SetIcon(const entry_ref& ref)
|
||||
InfoView::SetIcon(const PlaylistItem* item)
|
||||
{
|
||||
BNode node(&ref);
|
||||
BNodeInfo info(&node);
|
||||
return info.GetTrackerIcon(fIconBitmap, B_LARGE_ICON);
|
||||
return item->GetIcon(fIconBitmap, B_LARGE_ICON);
|
||||
}
|
||||
|
||||
|
||||
@ -180,14 +179,14 @@ InfoWin::InfoWin(BPoint leftTop, Controller* controller)
|
||||
rect.right - 10,
|
||||
20 + fh.ascent + 5),
|
||||
"filename", "");
|
||||
AddChild(fFilenameView);
|
||||
AddChild(fFilenameView);
|
||||
fFilenameView->SetFont(&bigFont);
|
||||
fFilenameView->SetViewColor(fInfoView->ViewColor());
|
||||
fFilenameView->SetLowColor(fInfoView->ViewColor());
|
||||
#ifdef B_BEOS_VERSION_DANO /* maybe we should support that as well ? */
|
||||
fFilenameView->SetTruncation(B_TRUNCATE_END);
|
||||
#endif
|
||||
|
||||
|
||||
rect.top = BASE_HEIGHT;
|
||||
|
||||
BRect lr(rect);
|
||||
@ -403,9 +402,9 @@ printf("InfoWin::Update(0x%08lx)\n", which);
|
||||
bigtime_t v;
|
||||
|
||||
//s << d << "µs; ";
|
||||
|
||||
|
||||
d /= 1000;
|
||||
|
||||
|
||||
v = d / (3600 * 1000);
|
||||
d = d % (3600 * 1000);
|
||||
bool hours = v > 0;
|
||||
@ -423,13 +422,13 @@ printf("InfoWin::Update(0x%08lx)\n", which);
|
||||
s << "\n";
|
||||
fContentsView->Insert(s.String());
|
||||
// TODO: demux/video/audio/... perfs (Kb/s)
|
||||
|
||||
|
||||
fLabelsView->Insert("Display Mode\n");
|
||||
if (fController->IsOverlayActive())
|
||||
fContentsView->Insert("Overlay\n");
|
||||
else
|
||||
fContentsView->Insert("DrawBitmap\n");
|
||||
|
||||
|
||||
fLabelsView->Insert("\n");
|
||||
fContentsView->Insert("\n");
|
||||
}
|
||||
@ -441,8 +440,8 @@ printf("InfoWin::Update(0x%08lx)\n", which);
|
||||
if (which & INFO_FILE) {
|
||||
bool iconSet = false;
|
||||
if (fController->HasFile()) {
|
||||
entry_ref ref = fController->Ref();
|
||||
iconSet = fInfoView->SetIcon(ref) == B_OK;
|
||||
const PlaylistItem* item = fController->Item();
|
||||
iconSet = fInfoView->SetIcon(item) == B_OK;
|
||||
media_file_format fileFormat;
|
||||
BString s;
|
||||
if (fController->GetFileFormatInfo(&fileFormat) == B_OK) {
|
||||
@ -470,7 +469,7 @@ printf("InfoWin::Update(0x%08lx)\n", which);
|
||||
}
|
||||
|
||||
if ((which & INFO_COPYRIGHT) && fController->HasFile()) {
|
||||
|
||||
|
||||
BString s;
|
||||
if (fController->GetCopyright(&s) == B_OK && s.Length() > 0) {
|
||||
fLabelsView->Insert("Copyright\n\n");
|
||||
@ -480,6 +479,6 @@ printf("InfoWin::Update(0x%08lx)\n", which);
|
||||
}
|
||||
|
||||
fController->Unlock();
|
||||
|
||||
|
||||
ResizeToPreferred();
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ Application MediaPlayer :
|
||||
|
||||
# playlist
|
||||
CopyPLItemsCommand.cpp
|
||||
EntryRefPlaylistItem.cpp
|
||||
FilePlaylistItem.cpp
|
||||
ImportPLItemsCommand.cpp
|
||||
ListViews.cpp
|
||||
MovePLItemsCommand.cpp
|
||||
@ -64,6 +64,7 @@ Application MediaPlayer :
|
||||
PlaylistListView.cpp
|
||||
PlaylistObserver.cpp
|
||||
PlaylistWindow.cpp
|
||||
PLItemsCommand.cpp
|
||||
RandomizePLItemsCommand.cpp
|
||||
RemovePLItemsCommand.cpp
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* MainWin.cpp - Media Player for the Haiku Operating System
|
||||
*
|
||||
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
||||
* Copyright (C) 2007-2008 Stephan Aßmus <superstippi@gmx.de> (GPL->MIT ok)
|
||||
* Copyright (C) 2007-2009 Stephan Aßmus <superstippi@gmx.de> (GPL->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
|
||||
@ -20,6 +20,7 @@
|
||||
* USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MainWin.h"
|
||||
|
||||
#include <math.h>
|
||||
@ -45,6 +46,7 @@
|
||||
#include "ControllerObserver.h"
|
||||
#include "MainApp.h"
|
||||
#include "PeakView.h"
|
||||
#include "PlaylistItem.h"
|
||||
#include "PlaylistObserver.h"
|
||||
#include "PlaylistWindow.h"
|
||||
#include "Settings.h"
|
||||
@ -379,33 +381,35 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
break;
|
||||
|
||||
// PlaylistObserver messages
|
||||
case MSG_PLAYLIST_REF_ADDED: {
|
||||
entry_ref ref;
|
||||
case MSG_PLAYLIST_ITEM_ADDED:
|
||||
{
|
||||
PlaylistItem* item;
|
||||
int32 index;
|
||||
if (msg->FindRef("refs", &ref) == B_OK
|
||||
if (msg->FindPointer("item", (void**)&item) == B_OK
|
||||
&& msg->FindInt32("index", &index) == B_OK) {
|
||||
_AddPlaylistItem(ref, index);
|
||||
_AddPlaylistItem(item, index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_REF_REMOVED: {
|
||||
case MSG_PLAYLIST_ITEM_REMOVED:
|
||||
{
|
||||
int32 index;
|
||||
if (msg->FindInt32("index", &index) == B_OK) {
|
||||
if (msg->FindInt32("index", &index) == B_OK)
|
||||
_RemovePlaylistItem(index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_CURRENT_REF_CHANGED: {
|
||||
case MSG_PLAYLIST_CURRENT_ITEM_CHANGED:
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
int32 index;
|
||||
if (msg->FindInt32("index", &index) < B_OK
|
||||
|| index != fPlaylist->CurrentRefIndex())
|
||||
|| index != fPlaylist->CurrentItemIndex())
|
||||
break;
|
||||
entry_ref ref;
|
||||
if (fPlaylist->GetRefAt(index, &ref) == B_OK) {
|
||||
printf("open ref: %s\n", ref.name);
|
||||
OpenFile(ref);
|
||||
PlaylistItemRef item(fPlaylist->ItemAt(index));
|
||||
if (item.Get() != NULL) {
|
||||
printf("open playlist item: %s\n", item->Name().String());
|
||||
OpenPlaylistItem(item);
|
||||
_MarkPlaylistItem(index);
|
||||
}
|
||||
break;
|
||||
@ -416,8 +420,8 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
bool hadNext = fPlaylist->SetCurrentRefIndex(
|
||||
fPlaylist->CurrentRefIndex() + 1);
|
||||
bool hadNext = fPlaylist->SetCurrentItemIndex(
|
||||
fPlaylist->CurrentItemIndex() + 1);
|
||||
if (!hadNext) {
|
||||
if (fHasVideo) {
|
||||
if (fCloseWhenDonePlayingMovie)
|
||||
@ -434,7 +438,8 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
// notification
|
||||
// _UpdatePlaylistMenu();
|
||||
break;
|
||||
case MSG_CONTROLLER_VIDEO_TRACK_CHANGED: {
|
||||
case MSG_CONTROLLER_VIDEO_TRACK_CHANGED:
|
||||
{
|
||||
int32 index;
|
||||
if (msg->FindInt32("index", &index) == B_OK) {
|
||||
BMenuItem* item = fVideoTrackMenu->ItemAt(index);
|
||||
@ -443,7 +448,8 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_CONTROLLER_AUDIO_TRACK_CHANGED: {
|
||||
case MSG_CONTROLLER_AUDIO_TRACK_CHANGED:
|
||||
{
|
||||
int32 index;
|
||||
if (msg->FindInt32("index", &index) == B_OK) {
|
||||
BMenuItem* item = fAudioTrackMenu->ItemAt(index);
|
||||
@ -452,25 +458,29 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED: {
|
||||
case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED:
|
||||
{
|
||||
uint32 state;
|
||||
if (msg->FindInt32("state", (int32*)&state) == B_OK)
|
||||
fControls->SetPlaybackState(state);
|
||||
break;
|
||||
}
|
||||
case MSG_CONTROLLER_POSITION_CHANGED: {
|
||||
case MSG_CONTROLLER_POSITION_CHANGED:
|
||||
{
|
||||
float position;
|
||||
if (msg->FindFloat("position", &position) == B_OK)
|
||||
fControls->SetPosition(position);
|
||||
break;
|
||||
}
|
||||
case MSG_CONTROLLER_VOLUME_CHANGED: {
|
||||
case MSG_CONTROLLER_VOLUME_CHANGED:
|
||||
{
|
||||
float volume;
|
||||
if (msg->FindFloat("volume", &volume) == B_OK)
|
||||
fControls->SetVolume(volume);
|
||||
break;
|
||||
}
|
||||
case MSG_CONTROLLER_MUTED_CHANGED: {
|
||||
case MSG_CONTROLLER_MUTED_CHANGED:
|
||||
{
|
||||
bool muted;
|
||||
if (msg->FindBool("muted", &muted) == B_OK)
|
||||
fControls->SetMuted(muted);
|
||||
@ -481,7 +491,8 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
case M_FILE_NEWPLAYER:
|
||||
gMainApp->NewWindow();
|
||||
break;
|
||||
case M_FILE_OPEN: {
|
||||
case M_FILE_OPEN:
|
||||
{
|
||||
BMessenger target(this);
|
||||
BMessage result(B_REFS_RECEIVED);
|
||||
BMessage appMessage(M_SHOW_OPEN_PANEL);
|
||||
@ -499,6 +510,7 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
ShowPlaylistWindow();
|
||||
break;
|
||||
case B_ABOUT_REQUESTED:
|
||||
{
|
||||
BAlert *alert;
|
||||
alert = new BAlert("about", NAME"\n\n Written by Marcus Overhagen "
|
||||
", Stephan Aßmus and Frederik Modéen", "Thanks");
|
||||
@ -510,6 +522,7 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
alert->Go(NULL); // Asynchronous mode
|
||||
}
|
||||
break;
|
||||
}
|
||||
case M_FILE_CLOSE:
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
@ -664,12 +677,13 @@ MainWin::MessageReceived(BMessage *msg)
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case M_SET_PLAYLIST_POSITION: {
|
||||
case M_SET_PLAYLIST_POSITION:
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
int32 index;
|
||||
if (msg->FindInt32("index", &index) == B_OK)
|
||||
fPlaylist->SetCurrentRefIndex(index);
|
||||
fPlaylist->SetCurrentItemIndex(index);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -731,18 +745,18 @@ MainWin::QuitRequested()
|
||||
|
||||
|
||||
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) {
|
||||
BAutolock _(fPlaylist);
|
||||
if (fPlaylist->CountItems() == 1) {
|
||||
// display error if this is the only file we're supposed to play
|
||||
BString message;
|
||||
message << "The file '";
|
||||
message << ref.name;
|
||||
message << item->Name();
|
||||
message << "' could not be opened.\n\n";
|
||||
|
||||
if (err == B_MEDIA_NO_HANDLER) {
|
||||
@ -757,7 +771,7 @@ MainWin::OpenFile(const entry_ref &ref)
|
||||
(new BAlert("error", message.String(), "OK"))->Go();
|
||||
} else {
|
||||
// just go to the next file and don't bother user
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->CurrentRefIndex() + 1);
|
||||
fPlaylist->SetCurrentItemIndex(fPlaylist->CurrentItemIndex() + 1);
|
||||
}
|
||||
fHasFile = false;
|
||||
fHasVideo = false;
|
||||
@ -767,7 +781,7 @@ MainWin::OpenFile(const entry_ref &ref)
|
||||
fHasFile = true;
|
||||
fHasVideo = fController->VideoTrackCount() != 0;
|
||||
fHasAudio = fController->AudioTrackCount() != 0;
|
||||
SetTitle(ref.name);
|
||||
SetTitle(item->Name().String());
|
||||
}
|
||||
_SetupWindow();
|
||||
}
|
||||
@ -1398,7 +1412,7 @@ MainWin::_KeyDown(BMessage *msg)
|
||||
BAutolock _(fPlaylist);
|
||||
BMessage removeMessage(M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH);
|
||||
removeMessage.AddInt32("playlist index",
|
||||
fPlaylist->CurrentRefIndex());
|
||||
fPlaylist->CurrentItemIndex());
|
||||
fPlaylistWindow->PostMessage(&removeMessage);
|
||||
return B_OK;
|
||||
}
|
||||
@ -1592,26 +1606,24 @@ MainWin::_UpdatePlaylistMenu()
|
||||
|
||||
int32 count = fPlaylist->CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
entry_ref ref;
|
||||
if (fPlaylist->GetRefAt(i, &ref) < B_OK)
|
||||
continue;
|
||||
_AddPlaylistItem(ref, i);
|
||||
PlaylistItem* item = fPlaylist->ItemAtFast(i);
|
||||
_AddPlaylistItem(item, i);
|
||||
}
|
||||
fPlaylistMenu->SetTargetForItems(this);
|
||||
|
||||
_MarkPlaylistItem(fPlaylist->CurrentRefIndex());
|
||||
_MarkPlaylistItem(fPlaylist->CurrentItemIndex());
|
||||
|
||||
fPlaylist->Unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWin::_AddPlaylistItem(const entry_ref& ref, int32 index)
|
||||
MainWin::_AddPlaylistItem(PlaylistItem* item, int32 index)
|
||||
{
|
||||
BMessage* message = new BMessage(M_SET_PLAYLIST_POSITION);
|
||||
message->AddInt32("index", index);
|
||||
BMenuItem* item = new BMenuItem(ref.name, message);
|
||||
fPlaylistMenu->AddItem(item, index);
|
||||
BMenuItem* menuItem = new BMenuItem(item->Name().String(), message);
|
||||
fPlaylistMenu->AddItem(menuItem, index);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* MainWin.h - Media Player for the Haiku Operating System
|
||||
*
|
||||
* 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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -31,6 +31,7 @@
|
||||
#include "InfoWin.h"
|
||||
#include "ListenerAdapter.h"
|
||||
#include "Playlist.h"
|
||||
#include "PlaylistItem.h"
|
||||
#include "VideoView.h"
|
||||
|
||||
class ControllerObserver;
|
||||
@ -51,18 +52,18 @@ public:
|
||||
virtual void WindowActivated(bool active);
|
||||
virtual bool QuitRequested();
|
||||
|
||||
void OpenFile(const entry_ref& ref);
|
||||
|
||||
void OpenPlaylistItem(const PlaylistItemRef& item);
|
||||
|
||||
void ShowFileInfo();
|
||||
void ShowPlaylistWindow();
|
||||
void ShowSettingsWindow();
|
||||
|
||||
|
||||
void VideoFormatChange(int width, int height,
|
||||
float widthScale, float heightScale);
|
||||
|
||||
private:
|
||||
void _RefsReceived(BMessage *message);
|
||||
|
||||
void _RefsReceived(BMessage* message);
|
||||
|
||||
void _SetupWindow();
|
||||
void _CreateMenu();
|
||||
void _SetupTrackMenus();
|
||||
@ -70,7 +71,7 @@ private:
|
||||
void _ResizeWindow(int percent);
|
||||
void _ResizeVideoView(int x, int y, int width,
|
||||
int height);
|
||||
|
||||
|
||||
void _MouseDown(BMessage* message,
|
||||
BView* originalHandler);
|
||||
void _MouseMoved(BMessage* message,
|
||||
@ -78,7 +79,7 @@ private:
|
||||
void _MouseUp(BMessage* message);
|
||||
void _ShowContextMenu(const BPoint& screenPoint);
|
||||
status_t _KeyDown(BMessage* message);
|
||||
|
||||
|
||||
void _ToggleFullscreen();
|
||||
void _ToggleKeepAspectRatio();
|
||||
void _ToggleAlwaysOnTop();
|
||||
@ -86,10 +87,10 @@ private:
|
||||
void _ToggleNoMenu();
|
||||
void _ToggleNoControls();
|
||||
void _ToggleNoBorderNoMenu();
|
||||
|
||||
|
||||
void _UpdateControlsEnabledStatus();
|
||||
void _UpdatePlaylistMenu();
|
||||
void _AddPlaylistItem(const entry_ref& ref,
|
||||
void _AddPlaylistItem(PlaylistItem* item,
|
||||
int32 index);
|
||||
void _RemovePlaylistItem(int32 index);
|
||||
void _MarkPlaylistItem(int32 index);
|
||||
@ -103,7 +104,7 @@ private:
|
||||
ControllerView* fControls;
|
||||
InfoWin* fInfoWin;
|
||||
PlaylistWindow* fPlaylistWindow;
|
||||
|
||||
|
||||
BMenu* fFileMenu;
|
||||
BMenu* fAudioMenu;
|
||||
BMenu* fVideoMenu;
|
||||
@ -112,11 +113,11 @@ private:
|
||||
BMenu* fSettingsMenu;
|
||||
BMenu* fPlaylistMenu;
|
||||
BMenu* fDebugMenu;
|
||||
|
||||
|
||||
bool fHasFile;
|
||||
bool fHasVideo;
|
||||
bool fHasAudio;
|
||||
|
||||
|
||||
Playlist* fPlaylist;
|
||||
PlaylistObserver* fPlaylistObserver;
|
||||
Controller* fController;
|
||||
|
@ -1,11 +1,7 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright © 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "CopyPLItemsCommand.h"
|
||||
|
||||
#include <new>
|
||||
@ -21,24 +17,31 @@ using std::nothrow;
|
||||
|
||||
CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist,
|
||||
const int32* indices, int32 count, int32 toIndex)
|
||||
: Command()
|
||||
, fPlaylist(playlist)
|
||||
, fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL)
|
||||
, fToIndex(toIndex)
|
||||
, fCount(count)
|
||||
:
|
||||
PLItemsCommand(),
|
||||
fPlaylist(playlist),
|
||||
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
|
||||
fToIndex(toIndex),
|
||||
fCount(count),
|
||||
fItemsCopied(false)
|
||||
{
|
||||
if (!indices || !fPlaylist || !fRefs) {
|
||||
if (!indices || !fPlaylist || !fItems) {
|
||||
// indicate a bad object state
|
||||
delete[] fRefs;
|
||||
fRefs = NULL;
|
||||
delete[] fItems;
|
||||
fItems = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(fItems, 0, sizeof(PlaylistItem*) * fCount);
|
||||
|
||||
// init original entries and
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
if (fPlaylist->GetRefAt(indices[i], &fRefs[i]) < B_OK) {
|
||||
delete[] fRefs;
|
||||
fRefs = NULL;
|
||||
PlaylistItem* item = fPlaylist->ItemAt(indices[i]);
|
||||
if (item != NULL)
|
||||
fItems[i] = item->Clone();
|
||||
if (fItems[i] == NULL) {
|
||||
// indicate a bad object state
|
||||
_CleanUp(fItems, fCount, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -47,14 +50,14 @@ CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist,
|
||||
|
||||
CopyPLItemsCommand::~CopyPLItemsCommand()
|
||||
{
|
||||
delete[] fRefs;
|
||||
_CleanUp(fItems, fCount, !fItemsCopied);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CopyPLItemsCommand::InitCheck()
|
||||
{
|
||||
if (!fPlaylist || !fRefs)
|
||||
if (!fPlaylist || !fItems)
|
||||
return B_NO_INIT;
|
||||
return B_OK;
|
||||
}
|
||||
@ -67,18 +70,17 @@ CopyPLItemsCommand::Perform()
|
||||
|
||||
status_t ret = B_OK;
|
||||
|
||||
fItemsCopied = true;
|
||||
|
||||
// add refs to playlist at the insertion index
|
||||
int32 index = fToIndex;
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
if (!fPlaylist->AddRef(fRefs[i], index++)) {
|
||||
if (!fPlaylist->AddItem(fItems[i], index++)) {
|
||||
ret = B_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret < B_OK)
|
||||
return ret;
|
||||
|
||||
return B_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -87,20 +89,19 @@ CopyPLItemsCommand::Undo()
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
// remember currently playling ref in case we copy items over it
|
||||
entry_ref currentRef;
|
||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
||||
¤tRef) == B_OK;
|
||||
fItemsCopied = false;
|
||||
// remember currently playling item in case we copy items over it
|
||||
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||
|
||||
// remove refs from playlist
|
||||
int32 index = fToIndex;
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
fPlaylist->RemoveRef(index++, false);
|
||||
fPlaylist->RemoveItem(index++, false);
|
||||
}
|
||||
|
||||
// take care about currently played ref
|
||||
if (adjustCurrentRef)
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
||||
// take care about currently played item
|
||||
if (current != NULL)
|
||||
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -1,28 +1,22 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright © 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef COPY_PL_ITEMS_COMMAND_H
|
||||
#define COPY_PL_ITEMS_COMMAND_H
|
||||
|
||||
|
||||
#include "Command.h"
|
||||
#include "PLItemsCommand.h"
|
||||
|
||||
class Playlist;
|
||||
struct entry_ref;
|
||||
|
||||
class CopyPLItemsCommand : public Command {
|
||||
public:
|
||||
class CopyPLItemsCommand : public PLItemsCommand {
|
||||
public:
|
||||
CopyPLItemsCommand(
|
||||
Playlist* playlist,
|
||||
const int32* indices,
|
||||
int32 count,
|
||||
int32 toIndex);
|
||||
virtual ~CopyPLItemsCommand();
|
||||
|
||||
|
||||
virtual status_t InitCheck();
|
||||
|
||||
virtual status_t Perform();
|
||||
@ -30,11 +24,12 @@ class CopyPLItemsCommand : public Command {
|
||||
|
||||
virtual void GetName(BString& name);
|
||||
|
||||
private:
|
||||
private:
|
||||
Playlist* fPlaylist;
|
||||
entry_ref* fRefs;
|
||||
PlaylistItem** fItems;
|
||||
int32 fToIndex;
|
||||
int32 fCount;
|
||||
bool fItemsCopied;
|
||||
};
|
||||
|
||||
#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
|
300
src/apps/mediaplayer/playlist/FilePlaylistItem.cpp
Normal file
300
src/apps/mediaplayer/playlist/FilePlaylistItem.cpp
Normal file
@ -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);
|
||||
}
|
||||
|
58
src/apps/mediaplayer/playlist/FilePlaylistItem.h
Normal file
58
src/apps/mediaplayer/playlist/FilePlaylistItem.h
Normal file
@ -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.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "ImportPLItemsCommand.h"
|
||||
@ -15,6 +12,7 @@
|
||||
#include <Autolock.h>
|
||||
|
||||
#include "Playlist.h"
|
||||
#include "PlaylistItem.h"
|
||||
|
||||
|
||||
using std::nothrow;
|
||||
@ -22,16 +20,20 @@ using std::nothrow;
|
||||
|
||||
ImportPLItemsCommand::ImportPLItemsCommand(Playlist* playlist,
|
||||
const BMessage* refsMessage, int32 toIndex)
|
||||
: Command()
|
||||
, fPlaylist(playlist)
|
||||
:
|
||||
PLItemsCommand(),
|
||||
fPlaylist(playlist),
|
||||
|
||||
, fOldRefs(NULL)
|
||||
, fOldCount(0)
|
||||
fOldItems(NULL),
|
||||
fOldCount(0),
|
||||
|
||||
, fNewRefs(NULL)
|
||||
, fNewCount(0)
|
||||
fNewItems(NULL),
|
||||
fNewCount(0),
|
||||
|
||||
, fToIndex(toIndex)
|
||||
fToIndex(toIndex),
|
||||
fPlaylingIndex(0),
|
||||
|
||||
fItemsAdded(false)
|
||||
{
|
||||
if (!fPlaylist)
|
||||
return;
|
||||
@ -47,38 +49,40 @@ ImportPLItemsCommand::ImportPLItemsCommand(Playlist* playlist,
|
||||
return;
|
||||
}
|
||||
|
||||
fNewRefs = new (nothrow) entry_ref[fNewCount];
|
||||
if (!fNewRefs)
|
||||
fNewItems = new (nothrow) PlaylistItem*[fNewCount];
|
||||
if (!fNewItems)
|
||||
return;
|
||||
memset(fNewItems, 0, fNewCount * sizeof(PlaylistItem*));
|
||||
|
||||
// init new entries
|
||||
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
|
||||
delete[] fNewRefs;
|
||||
fNewRefs = NULL;
|
||||
_CleanUp(fNewItems, fNewCount, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fPlaylingIndex = fPlaylist->CurrentItemIndex();
|
||||
|
||||
if (fToIndex < 0) {
|
||||
fOldCount = fPlaylist->CountItems();
|
||||
if (fOldCount > 0) {
|
||||
fOldRefs = new (nothrow) entry_ref[fOldCount];
|
||||
if (!fOldRefs) {
|
||||
fOldItems = new (nothrow) PlaylistItem*[fOldCount];
|
||||
if (!fOldItems) {
|
||||
// indicate bad object init
|
||||
delete[] fNewRefs;
|
||||
fNewRefs = NULL;
|
||||
return;
|
||||
_CleanUp(fNewItems, fNewCount, true);
|
||||
}
|
||||
memset(fOldItems, 0, fOldCount * sizeof(PlaylistItem*));
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
delete[] fNewRefs;
|
||||
fNewRefs = NULL;
|
||||
_CleanUp(fNewItems, fNewCount, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -87,15 +91,15 @@ ImportPLItemsCommand::ImportPLItemsCommand(Playlist* playlist,
|
||||
|
||||
ImportPLItemsCommand::~ImportPLItemsCommand()
|
||||
{
|
||||
delete[] fOldRefs;
|
||||
delete[] fNewRefs;
|
||||
_CleanUp(fOldItems, fOldCount, fItemsAdded);
|
||||
_CleanUp(fNewItems, fNewCount, !fItemsAdded);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ImportPLItemsCommand::InitCheck()
|
||||
{
|
||||
if (!fPlaylist || !fNewRefs)
|
||||
if (!fPlaylist || !fNewItems)
|
||||
return B_NO_INIT;
|
||||
return B_OK;
|
||||
}
|
||||
@ -106,9 +110,11 @@ ImportPLItemsCommand::Perform()
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
fItemsAdded = true;
|
||||
|
||||
int32 index = fToIndex;
|
||||
if (fToIndex < 0) {
|
||||
fPlaylist->MakeEmpty();
|
||||
fPlaylist->MakeEmpty(false);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@ -116,13 +122,13 @@ ImportPLItemsCommand::Perform()
|
||||
|
||||
// add refs to playlist at the insertion index
|
||||
for (int32 i = 0; i < fNewCount; i++) {
|
||||
if (!fPlaylist->AddRef(fNewRefs[i], index++))
|
||||
if (!fPlaylist->AddItem(fNewItems[i], index++))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (startPlaying) {
|
||||
// open first file
|
||||
fPlaylist->SetCurrentRefIndex(0);
|
||||
fPlaylist->SetCurrentItemIndex(0);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -134,17 +140,22 @@ ImportPLItemsCommand::Undo()
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
fItemsAdded = false;
|
||||
|
||||
if (fToIndex < 0) {
|
||||
// remove new refs from playlist and restore old refs
|
||||
fPlaylist->MakeEmpty();
|
||||
// remove new items from playlist and restore old refs
|
||||
fPlaylist->MakeEmpty(false);
|
||||
for (int32 i = 0; i < fOldCount; i++) {
|
||||
if (!fPlaylist->AddRef(fOldRefs[i], i))
|
||||
if (!fPlaylist->AddItem(fOldItems[i], i))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
// Restore previously playing item
|
||||
if (fPlaylingIndex >= 0)
|
||||
fPlaylist->SetCurrentItemIndex(fPlaylingIndex);
|
||||
} else {
|
||||
// remove refs from playlist
|
||||
// remove new items from playlist
|
||||
for (int32 i = 0; i < fNewCount; i++) {
|
||||
fPlaylist->RemoveRef(fToIndex);
|
||||
fPlaylist->RemoveItem(fToIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,3 +171,4 @@ ImportPLItemsCommand::GetName(BString& name)
|
||||
else
|
||||
name << "Import Entry";
|
||||
}
|
||||
|
||||
|
@ -1,28 +1,23 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef IMPORT_PL_ITEMS_COMMAND_H
|
||||
#define IMPORT_PL_ITEMS_COMMAND_H
|
||||
|
||||
|
||||
#include "Command.h"
|
||||
#include "PLItemsCommand.h"
|
||||
|
||||
class BMessage;
|
||||
class Playlist;
|
||||
struct entry_ref;
|
||||
|
||||
class ImportPLItemsCommand : public Command {
|
||||
public:
|
||||
class ImportPLItemsCommand : public PLItemsCommand {
|
||||
public:
|
||||
ImportPLItemsCommand(
|
||||
Playlist* playlist,
|
||||
const BMessage* refsMessage,
|
||||
int32 toIndex);
|
||||
virtual ~ImportPLItemsCommand();
|
||||
|
||||
|
||||
virtual status_t InitCheck();
|
||||
|
||||
virtual status_t Perform();
|
||||
@ -30,13 +25,15 @@ class ImportPLItemsCommand : public Command {
|
||||
|
||||
virtual void GetName(BString& name);
|
||||
|
||||
private:
|
||||
private:
|
||||
Playlist* fPlaylist;
|
||||
entry_ref* fOldRefs;
|
||||
PlaylistItem** fOldItems;
|
||||
int32 fOldCount;
|
||||
entry_ref* fNewRefs;
|
||||
PlaylistItem** fNewItems;
|
||||
int32 fNewCount;
|
||||
int32 fToIndex;
|
||||
int32 fPlaylingIndex;
|
||||
bool fItemsAdded;
|
||||
};
|
||||
|
||||
#endif // IMPORT_PL_ITEMS_COMMAND_H
|
||||
|
@ -1,9 +1,6 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "MovePLItemsCommand.h"
|
||||
@ -21,20 +18,22 @@ using std::nothrow;
|
||||
|
||||
MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
|
||||
const int32* indices, int32 count, int32 toIndex)
|
||||
: Command()
|
||||
, fPlaylist(playlist)
|
||||
, fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL)
|
||||
, fIndices(count > 0 ? new (nothrow) int32[count] : NULL)
|
||||
, fToIndex(toIndex)
|
||||
, fCount(count)
|
||||
:
|
||||
PLItemsCommand(),
|
||||
fPlaylist(playlist),
|
||||
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
|
||||
fIndices(count > 0 ? new (nothrow) int32[count] : NULL),
|
||||
fToIndex(toIndex),
|
||||
fCount(count)
|
||||
{
|
||||
if (!indices || !fPlaylist || !fRefs || !fIndices) {
|
||||
if (!indices || !fPlaylist || !fItems || !fIndices) {
|
||||
// indicate a bad object state
|
||||
delete[] fRefs;
|
||||
fRefs = NULL;
|
||||
delete[] fItems;
|
||||
fItems = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(fItems, 0, sizeof(PlaylistItem*) * fCount);
|
||||
memcpy(fIndices, indices, fCount * sizeof(int32));
|
||||
|
||||
// init original entry indices and
|
||||
@ -42,10 +41,11 @@ MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
|
||||
// are removed before that index
|
||||
int32 itemsBeforeIndex = 0;
|
||||
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
|
||||
delete[] fRefs;
|
||||
fRefs = NULL;
|
||||
delete[] fItems;
|
||||
fItems = NULL;
|
||||
return;
|
||||
}
|
||||
if (fIndices[i] < fToIndex)
|
||||
@ -57,7 +57,7 @@ MovePLItemsCommand::MovePLItemsCommand(Playlist* playlist,
|
||||
|
||||
MovePLItemsCommand::~MovePLItemsCommand()
|
||||
{
|
||||
delete[] fRefs;
|
||||
delete[] fItems;
|
||||
delete[] fIndices;
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ MovePLItemsCommand::~MovePLItemsCommand()
|
||||
status_t
|
||||
MovePLItemsCommand::InitCheck()
|
||||
{
|
||||
if (!fRefs)
|
||||
if (!fItems)
|
||||
return B_NO_INIT;
|
||||
|
||||
// analyse the move, don't return B_OK in case
|
||||
@ -106,21 +106,19 @@ MovePLItemsCommand::Perform()
|
||||
|
||||
status_t ret = B_OK;
|
||||
|
||||
// remember currently playling ref in case we move it
|
||||
entry_ref currentRef;
|
||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
||||
¤tRef) == B_OK;
|
||||
// remember currently playling item in case we move it
|
||||
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||
|
||||
// remove refs from playlist
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
// "- 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
|
||||
int32 index = fToIndex;
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
if (!fPlaylist->AddRef(fRefs[i], index++)) {
|
||||
if (!fPlaylist->AddItem(fItems[i], index++)) {
|
||||
ret = B_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
@ -128,9 +126,9 @@ MovePLItemsCommand::Perform()
|
||||
if (ret < B_OK)
|
||||
return ret;
|
||||
|
||||
// take care about currently played ref
|
||||
if (adjustCurrentRef)
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
||||
// take care about currently played item
|
||||
if (current != NULL)
|
||||
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -143,20 +141,18 @@ MovePLItemsCommand::Undo()
|
||||
|
||||
status_t ret = B_OK;
|
||||
|
||||
// remember currently playling ref in case we move it
|
||||
entry_ref currentRef;
|
||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
||||
¤tRef) == B_OK;
|
||||
// remember currently playling item in case we move it
|
||||
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||
|
||||
// remove refs from playlist
|
||||
int32 index = fToIndex;
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
fPlaylist->RemoveRef(index++, false);
|
||||
fPlaylist->RemoveItem(index++, false);
|
||||
}
|
||||
|
||||
// add ref to playlist at remembered indices
|
||||
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;
|
||||
break;
|
||||
}
|
||||
@ -164,9 +160,9 @@ MovePLItemsCommand::Undo()
|
||||
if (ret < B_OK)
|
||||
return ret;
|
||||
|
||||
// take care about currently played ref
|
||||
if (adjustCurrentRef)
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
||||
// take care about currently played item
|
||||
if (current != NULL)
|
||||
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -1,20 +1,14 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef MOVE_PL_ITEMS_COMMAND_H
|
||||
#define MOVE_PL_ITEMS_COMMAND_H
|
||||
|
||||
|
||||
#include "Command.h"
|
||||
#include "PLItemsCommand.h"
|
||||
|
||||
class Playlist;
|
||||
struct entry_ref;
|
||||
|
||||
class MovePLItemsCommand : public Command {
|
||||
class MovePLItemsCommand : public PLItemsCommand {
|
||||
public:
|
||||
MovePLItemsCommand(
|
||||
Playlist* playlist,
|
||||
@ -22,7 +16,7 @@ class MovePLItemsCommand : public Command {
|
||||
int32 count,
|
||||
int32 toIndex);
|
||||
virtual ~MovePLItemsCommand();
|
||||
|
||||
|
||||
virtual status_t InitCheck();
|
||||
|
||||
virtual status_t Perform();
|
||||
@ -32,7 +26,7 @@ class MovePLItemsCommand : public Command {
|
||||
|
||||
private:
|
||||
Playlist* fPlaylist;
|
||||
entry_ref* fRefs;
|
||||
PlaylistItem** fItems;
|
||||
int32* fIndices;
|
||||
int32 fToIndex;
|
||||
int32 fCount;
|
||||
|
41
src/apps/mediaplayer/playlist/PLItemsCommand.cpp
Normal file
41
src/apps/mediaplayer/playlist/PLItemsCommand.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
24
src/apps/mediaplayer/playlist/PLItemsCommand.h
Normal file
24
src/apps/mediaplayer/playlist/PLItemsCommand.h
Normal file
@ -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,8 +2,8 @@
|
||||
* Playlist.cpp - Media Player for the Haiku Operating System
|
||||
*
|
||||
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
||||
* Copyright (C) 2007 Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright (C) 2008-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok)
|
||||
* Copyright (C) 2007-2009 Stephan Aßmus <superstippi@gmx.de> (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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -19,21 +19,27 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Playlist.h"
|
||||
|
||||
#include <debugger.h>
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <AppFileInfo.h>
|
||||
#include <Application.h>
|
||||
#include <Autolock.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <Message.h>
|
||||
#include <Mime.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <Path.h>
|
||||
#include <Roster.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "FilePlaylistItem.h"
|
||||
#include "FileReadWrite.h"
|
||||
|
||||
using std::nothrow;
|
||||
@ -42,19 +48,54 @@ using std::nothrow;
|
||||
|
||||
Playlist::Listener::Listener() {}
|
||||
Playlist::Listener::~Listener() {}
|
||||
void Playlist::Listener::RefAdded(const entry_ref& ref, int32 index) {}
|
||||
void Playlist::Listener::RefRemoved(int32 index) {}
|
||||
void Playlist::Listener::RefsSorted() {}
|
||||
void Playlist::Listener::CurrentRefChanged(int32 newIndex) {}
|
||||
void Playlist::Listener::ItemAdded(PlaylistItem* item, int32 index) {}
|
||||
void Playlist::Listener::ItemRemoved(int32 index) {}
|
||||
void Playlist::Listener::ItemsSorted() {}
|
||||
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 -
|
||||
|
||||
|
||||
Playlist::Playlist()
|
||||
: BLocker("playlist lock")
|
||||
, fRefs()
|
||||
, fCurrentIndex(-1)
|
||||
:
|
||||
BLocker("playlist lock"),
|
||||
fItems(),
|
||||
fCurrentIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -71,7 +112,7 @@ Playlist::~Playlist()
|
||||
// #pragma mark - archiving
|
||||
|
||||
|
||||
static const char* kPathKey = "path";
|
||||
static const char* kItemArchiveKey = "item";
|
||||
|
||||
|
||||
status_t
|
||||
@ -82,15 +123,21 @@ Playlist::Unarchive(const BMessage* archive)
|
||||
|
||||
MakeEmpty();
|
||||
|
||||
BString path;
|
||||
for (int32 i = 0; archive->FindString(kPathKey, i, &path) == B_OK; i++) {
|
||||
BEntry entry(path.String(), false);
|
||||
// don't follow links, we want to do that when opening files only
|
||||
entry_ref ref;
|
||||
if (entry.GetRef(&ref) != B_OK)
|
||||
BMessage itemArchive;
|
||||
for (int32 i = 0;
|
||||
archive->FindMessage(kItemArchiveKey, i, &itemArchive) == B_OK; i++) {
|
||||
|
||||
BArchivable* archivable = instantiate_object(&itemArchive);
|
||||
PlaylistItem* item = dynamic_cast<PlaylistItem*>(archivable);
|
||||
if (!item) {
|
||||
delete archivable;
|
||||
continue;
|
||||
if (!AddRef(ref))
|
||||
}
|
||||
|
||||
if (!AddItem(item)) {
|
||||
delete item;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -103,13 +150,14 @@ Playlist::Archive(BMessage* into) const
|
||||
if (into == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
int32 count = fRefs.CountItems();
|
||||
int32 count = CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
const entry_ref* ref = (entry_ref*)fRefs.ItemAtFast(i);
|
||||
BPath path(ref);
|
||||
if (path.InitCheck() != B_OK)
|
||||
continue;
|
||||
status_t ret = into->AddString(kPathKey, path.Path());
|
||||
const PlaylistItem* item = ItemAtFast(i);
|
||||
BMessage itemArchive;
|
||||
status_t ret = item->Archive(&itemArchive);
|
||||
if (ret != B_OK)
|
||||
return ret;
|
||||
ret = into->AddMessage(kItemArchiveKey, &itemArchive);
|
||||
if (ret != B_OK)
|
||||
return ret;
|
||||
}
|
||||
@ -145,7 +193,6 @@ Playlist::Unflatten(BDataIO* stream)
|
||||
if (ret != B_OK)
|
||||
return ret;
|
||||
|
||||
|
||||
return Unarchive(&archive);
|
||||
}
|
||||
|
||||
@ -177,54 +224,51 @@ Playlist::Flatten(BDataIO* stream) const
|
||||
|
||||
|
||||
void
|
||||
Playlist::MakeEmpty()
|
||||
Playlist::MakeEmpty(bool deleteItems)
|
||||
{
|
||||
int32 count = fRefs.CountItems();
|
||||
int32 count = CountItems();
|
||||
for (int32 i = count - 1; i >= 0; i--) {
|
||||
entry_ref* ref = (entry_ref*)fRefs.RemoveItem(i);
|
||||
_NotifyRefRemoved(i);
|
||||
delete ref;
|
||||
PlaylistItem* item = RemoveItem(i, false);
|
||||
_NotifyItemRemoved(i);
|
||||
if (deleteItems)
|
||||
item->RemoveReference();
|
||||
}
|
||||
SetCurrentRefIndex(-1);
|
||||
SetCurrentItemIndex(-1);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
Playlist::CountItems() const
|
||||
{
|
||||
return fRefs.CountItems();
|
||||
return fItems.CountItems();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Playlist::Sort()
|
||||
{
|
||||
fRefs.SortItems(playlist_cmp);
|
||||
_NotifyRefsSorted();
|
||||
fItems.SortItems(playlist_item_compare);
|
||||
_NotifyItemsSorted();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Playlist::AddRef(const entry_ref &ref)
|
||||
Playlist::AddItem(PlaylistItem* item)
|
||||
{
|
||||
return AddRef(ref, CountItems());
|
||||
return AddItem(item, CountItems());
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Playlist::AddRef(const entry_ref &ref, int32 index)
|
||||
Playlist::AddItem(PlaylistItem* item, int32 index)
|
||||
{
|
||||
entry_ref* copy = new (nothrow) entry_ref(ref);
|
||||
if (!copy)
|
||||
if (!fItems.AddItem(item, index))
|
||||
return false;
|
||||
if (!fRefs.AddItem(copy, index)) {
|
||||
delete copy;
|
||||
return false;
|
||||
}
|
||||
_NotifyRefAdded(ref, index);
|
||||
|
||||
if (index <= fCurrentIndex)
|
||||
SetCurrentRefIndex(fCurrentIndex + 1);
|
||||
SetCurrentItemIndex(fCurrentIndex + 1);
|
||||
|
||||
_NotifyItemAdded(item, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -244,85 +288,68 @@ Playlist::AdoptPlaylist(Playlist& other, int32 index)
|
||||
return false;
|
||||
// NOTE: this is not intended to merge two "equal" playlists
|
||||
// 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
|
||||
int32 count = other.fRefs.CountItems();
|
||||
int32 count = other.CountItems();
|
||||
for (int32 i = index; i < index + count; i++) {
|
||||
entry_ref* ref = (entry_ref*)fRefs.ItemAtFast(i);
|
||||
_NotifyRefAdded(*ref, i);
|
||||
PlaylistItem* item = ItemAtFast(i);
|
||||
_NotifyItemAdded(item, i);
|
||||
}
|
||||
if (index <= fCurrentIndex)
|
||||
SetCurrentRefIndex(fCurrentIndex + count);
|
||||
// empty the other list, so that the entry_refs are now ours
|
||||
other.fRefs.MakeEmpty();
|
||||
SetCurrentItemIndex(fCurrentIndex + count);
|
||||
// empty the other list, so that the PlaylistItems are now ours
|
||||
other.fItems.MakeEmpty();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
entry_ref
|
||||
Playlist::RemoveRef(int32 index, bool careAboutCurrentIndex)
|
||||
PlaylistItem*
|
||||
Playlist::RemoveItem(int32 index, bool careAboutCurrentIndex)
|
||||
{
|
||||
entry_ref _ref;
|
||||
entry_ref* ref = (entry_ref*)fRefs.RemoveItem(index);
|
||||
if (!ref)
|
||||
return _ref;
|
||||
_NotifyRefRemoved(index);
|
||||
_ref = *ref;
|
||||
delete ref;
|
||||
PlaylistItem* item = (PlaylistItem*)fItems.RemoveItem(index);
|
||||
if (!item)
|
||||
return NULL;
|
||||
_NotifyItemRemoved(index);
|
||||
|
||||
if (careAboutCurrentIndex) {
|
||||
if (index == fCurrentIndex)
|
||||
SetCurrentRefIndex(-1);
|
||||
if (index == fCurrentIndex && index >= CountItems())
|
||||
SetCurrentItemIndex(CountItems() - 1);
|
||||
else if (index < fCurrentIndex)
|
||||
SetCurrentRefIndex(fCurrentIndex - 1);
|
||||
SetCurrentItemIndex(fCurrentIndex - 1);
|
||||
}
|
||||
|
||||
return _ref;
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
Playlist::IndexOf(const entry_ref& _ref) const
|
||||
Playlist::IndexOf(PlaylistItem* item) const
|
||||
{
|
||||
int32 count = CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
entry_ref* ref = (entry_ref*)fRefs.ItemAtFast(i);
|
||||
if (*ref == _ref)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
return fItems.IndexOf(item);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Playlist::GetRefAt(int32 index, entry_ref* _ref) const
|
||||
PlaylistItem*
|
||||
Playlist::ItemAt(int32 index) const
|
||||
{
|
||||
if (!_ref)
|
||||
return B_BAD_VALUE;
|
||||
entry_ref* ref = (entry_ref*)fRefs.ItemAt(index);
|
||||
if (!ref)
|
||||
return B_BAD_INDEX;
|
||||
*_ref = *ref;
|
||||
|
||||
return B_OK;
|
||||
return (PlaylistItem*)fItems.ItemAt(index);
|
||||
}
|
||||
|
||||
|
||||
//bool
|
||||
//Playlist::HasRef(const entry_ref& ref) const
|
||||
//{
|
||||
// return IndexOf(ref) >= 0;
|
||||
//}
|
||||
|
||||
PlaylistItem*
|
||||
Playlist::ItemAtFast(int32 index) const
|
||||
{
|
||||
return (PlaylistItem*)fItems.ItemAtFast(index);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - navigation
|
||||
|
||||
|
||||
bool
|
||||
Playlist::SetCurrentRefIndex(int32 index)
|
||||
Playlist::SetCurrentItemIndex(int32 index)
|
||||
{
|
||||
bool result = true;
|
||||
if (index >= CountItems() || index < 0) {
|
||||
@ -334,13 +361,13 @@ Playlist::SetCurrentRefIndex(int32 index)
|
||||
return result;
|
||||
|
||||
fCurrentIndex = index;
|
||||
_NotifyCurrentRefChanged(fCurrentIndex);
|
||||
_NotifyCurrentItemChanged(fCurrentIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
Playlist::CurrentRefIndex() const
|
||||
Playlist::CurrentItemIndex() const
|
||||
{
|
||||
return fCurrentIndex;
|
||||
}
|
||||
@ -377,7 +404,7 @@ Playlist::RemoveListener(Listener* listener)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// #pragma mark - support
|
||||
|
||||
|
||||
void
|
||||
@ -409,7 +436,7 @@ Playlist::AppendRefs(const BMessage* refsReceivedMessage, int32 appendIndex)
|
||||
sortPlaylist = false;
|
||||
} else {
|
||||
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 (!sortPlaylist)
|
||||
subPlaylist.Sort();
|
||||
@ -426,7 +453,7 @@ Playlist::AppendRefs(const BMessage* refsReceivedMessage, int32 appendIndex)
|
||||
|
||||
if (startPlaying) {
|
||||
// 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)
|
||||
AppendToPlaylistRecursive(subRef, playlist);
|
||||
} else if (entry.IsFile()) {
|
||||
//printf("Is File\n");
|
||||
BString mimeString = _MIMEString(&ref);
|
||||
if (_IsMediaFile(mimeString)) {
|
||||
//printf("Adding\n");
|
||||
playlist->AddRef(ref);
|
||||
PlaylistItem* item = new (std::nothrow) FilePlaylistItem(ref);
|
||||
if (item == NULL || !playlist->AddItem(item))
|
||||
delete item;
|
||||
} else
|
||||
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());
|
||||
if (path.Path() != NULL) {
|
||||
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
|
||||
printf("Error - %s: [%lx]\n", strerror(err), (int32) err);
|
||||
} else
|
||||
@ -498,21 +528,7 @@ Playlist::AppendPlaylistToPlaylist(const entry_ref& ref, Playlist* playlist)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
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());
|
||||
}
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
@ -524,10 +540,29 @@ Playlist::_IsMediaFile(const BString& mimeString)
|
||||
if (fileType.GetSupertype(&superType) != B_OK)
|
||||
return false;
|
||||
|
||||
// TODO: some media files have other super types, I think
|
||||
// for example ASF has "application" super type... so it would
|
||||
// need special handling
|
||||
return (superType == "audio" || superType == "video");
|
||||
// try a shortcut first
|
||||
if (superType == "audio" || superType == "video")
|
||||
return true;
|
||||
|
||||
// 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
|
||||
Playlist::_NotifyRefAdded(const entry_ref& ref, int32 index) const
|
||||
Playlist::_NotifyItemAdded(PlaylistItem* item, int32 index) const
|
||||
{
|
||||
BList listeners(fListeners);
|
||||
int32 count = listeners.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
||||
listener->RefAdded(ref, index);
|
||||
listener->ItemAdded(item, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Playlist::_NotifyRefRemoved(int32 index) const
|
||||
Playlist::_NotifyItemRemoved(int32 index) const
|
||||
{
|
||||
BList listeners(fListeners);
|
||||
int32 count = listeners.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
||||
listener->RefRemoved(index);
|
||||
listener->ItemRemoved(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Playlist::_NotifyRefsSorted() const
|
||||
Playlist::_NotifyItemsSorted() const
|
||||
{
|
||||
BList listeners(fListeners);
|
||||
int32 count = listeners.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
||||
listener->RefsSorted();
|
||||
listener->ItemsSorted();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Playlist::_NotifyCurrentRefChanged(int32 newIndex) const
|
||||
Playlist::_NotifyCurrentItemChanged(int32 newIndex) const
|
||||
{
|
||||
BList listeners(fListeners);
|
||||
int32 count = listeners.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
Listener* listener = (Listener*)listeners.ItemAtFast(i);
|
||||
listener->CurrentRefChanged(newIndex);
|
||||
listener->CurrentItemChanged(newIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
* Playlist.h - Media Player for the Haiku Operating System
|
||||
*
|
||||
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
|
||||
* Copyright (C) 2007 Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright (C) 2008-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok)
|
||||
* Copyright (C) 2007-2009 Stephan Aßmus <superstippi@gmx.de> (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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -22,13 +22,15 @@
|
||||
#ifndef __PLAYLIST_H
|
||||
#define __PLAYLIST_H
|
||||
|
||||
#include <Entry.h>
|
||||
#include <List.h>
|
||||
#include <Locker.h>
|
||||
|
||||
#include "PlaylistItem.h"
|
||||
|
||||
class BDataIO;
|
||||
class BMessage;
|
||||
class BString;
|
||||
struct entry_ref;
|
||||
|
||||
|
||||
class Playlist : public BLocker {
|
||||
@ -38,12 +40,12 @@ public:
|
||||
Listener();
|
||||
virtual ~Listener();
|
||||
|
||||
virtual void RefAdded(const entry_ref& ref, int32 index);
|
||||
virtual void RefRemoved(int32 index);
|
||||
virtual void ItemAdded(PlaylistItem* item, int32 index);
|
||||
virtual void ItemRemoved(int32 index);
|
||||
|
||||
virtual void RefsSorted();
|
||||
virtual void ItemsSorted();
|
||||
|
||||
virtual void CurrentRefChanged(int32 newIndex);
|
||||
virtual void CurrentItemChanged(int32 newIndex);
|
||||
};
|
||||
|
||||
public:
|
||||
@ -58,26 +60,26 @@ public:
|
||||
|
||||
|
||||
// list functionality
|
||||
void MakeEmpty();
|
||||
void MakeEmpty(bool deleteItems = true);
|
||||
int32 CountItems() const;
|
||||
|
||||
void Sort();
|
||||
|
||||
bool AddRef(const entry_ref& ref);
|
||||
bool AddRef(const entry_ref& ref, int32 index);
|
||||
entry_ref RemoveRef(int32 index,
|
||||
bool AddItem(PlaylistItem* item);
|
||||
bool AddItem(PlaylistItem* item, int32 index);
|
||||
PlaylistItem* RemoveItem(int32 index,
|
||||
bool careAboutCurrentIndex = true);
|
||||
|
||||
bool AdoptPlaylist(Playlist& other);
|
||||
bool AdoptPlaylist(Playlist& other, int32 index);
|
||||
|
||||
int32 IndexOf(const entry_ref& ref) const;
|
||||
status_t GetRefAt(int32 index, entry_ref* ref) const;
|
||||
// bool HasRef(const entry_ref& ref) const;
|
||||
int32 IndexOf(PlaylistItem* item) const;
|
||||
PlaylistItem* ItemAt(int32 index) const;
|
||||
PlaylistItem* ItemAtFast(int32 index) const;
|
||||
|
||||
// navigating current ref
|
||||
bool SetCurrentRefIndex(int32 index);
|
||||
int32 CurrentRefIndex() const;
|
||||
bool SetCurrentItemIndex(int32 index);
|
||||
int32 CurrentItemIndex() const;
|
||||
|
||||
void GetSkipInfo(bool* canSkipPrevious,
|
||||
bool* canSkipNext) const;
|
||||
@ -95,20 +97,20 @@ public:
|
||||
Playlist* playlist);
|
||||
|
||||
private:
|
||||
static int playlist_cmp(const void* p1, const void* p2);
|
||||
static bool _IsMediaFile(const BString& mimeString);
|
||||
static bool _IsTextPlaylist(const BString& mimeString);
|
||||
static bool _IsBinaryPlaylist(const BString& mimeString);
|
||||
static bool _IsPlaylist(const BString& mimeString);
|
||||
static BString _MIMEString(const entry_ref* ref);
|
||||
void _NotifyRefAdded(const entry_ref& ref,
|
||||
|
||||
void _NotifyItemAdded(PlaylistItem*,
|
||||
int32 index) const;
|
||||
void _NotifyRefRemoved(int32 index) const;
|
||||
void _NotifyRefsSorted() const;
|
||||
void _NotifyCurrentRefChanged(int32 newIndex) const;
|
||||
void _NotifyItemRemoved(int32 index) const;
|
||||
void _NotifyItemsSorted() const;
|
||||
void _NotifyCurrentItemChanged(int32 newIndex) const;
|
||||
|
||||
private:
|
||||
BList fRefs;
|
||||
BList fItems;
|
||||
BList fListeners;
|
||||
|
||||
int32 fCurrentIndex;
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#include "PlaylistItem.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
PlaylistItem::Listener::Listener()
|
||||
{
|
||||
@ -22,13 +24,97 @@ void PlaylistItem::Listener::ItemChanged(const PlaylistItem* item)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
//#define DEBUG_INSTANCE_COUNT
|
||||
#ifdef DEBUG_INSTANCE_COUNT
|
||||
static vint32 sInstanceCount = 0;
|
||||
#endif
|
||||
|
||||
|
||||
PlaylistItem::PlaylistItem()
|
||||
{
|
||||
#ifdef DEBUG_INSTANCE_COUNT
|
||||
atomic_add(&sInstanceCount, 1);
|
||||
printf("%p->PlaylistItem::PlaylistItem() (%ld)\n", this, sInstanceCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
#define PLAYLIST_ITEM_H
|
||||
|
||||
#include <Archivable.h>
|
||||
#include <List.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <Referenceable.h>
|
||||
#include <String.h>
|
||||
|
||||
class BBitmap;
|
||||
class BDataIO;
|
||||
class BMediaFile;
|
||||
class BMessage;
|
||||
|
||||
class PlaylistItem {
|
||||
class PlaylistItem : public BArchivable, public Referenceable {
|
||||
public:
|
||||
class Listener {
|
||||
public:
|
||||
@ -26,35 +30,60 @@ public:
|
||||
PlaylistItem();
|
||||
virtual ~PlaylistItem();
|
||||
|
||||
virtual PlaylistItem* Clone() const = 0;
|
||||
|
||||
// archiving
|
||||
// virtual status_t Unarchive(const BMessage* archive) = 0;
|
||||
// virtual status_t Archive(BMessage* into) const = 0;
|
||||
//
|
||||
// virtual status_t Unflatten(BDataIO* stream) = 0;
|
||||
// virtual status_t Flatten(BDataIO* stream) const = 0;
|
||||
virtual status_t Archive(BMessage* into,
|
||||
bool deep = true) const = 0;
|
||||
|
||||
// properties
|
||||
virtual status_t SetName(const BString& name) = 0;
|
||||
virtual status_t GetName(BString& name) const = 0;
|
||||
// attributes
|
||||
typedef enum {
|
||||
ATTR_STRING_NAME = 'name',
|
||||
ATTR_STRING_KEYWORDS = 'kwrd',
|
||||
|
||||
virtual status_t SetTitle(const BString& title) = 0;
|
||||
virtual status_t GetTitle(BString& title) const = 0;
|
||||
ATTR_STRING_AUTHOR = 'auth',
|
||||
ATTR_STRING_ALBUM = 'albm',
|
||||
ATTR_STRING_TITLE = 'titl',
|
||||
|
||||
virtual status_t SetAuthor(const BString& author) = 0;
|
||||
virtual status_t GetAuthor(BString& author) const = 0;
|
||||
ATTR_INT32_TRACK = 'trck',
|
||||
ATTR_INT32_YEAR = 'year',
|
||||
ATTR_INT32_RATING = 'rtng',
|
||||
ATTR_INT32_BIT_RATE = 'btrt',
|
||||
|
||||
virtual status_t SetAlbum(const BString& album) = 0;
|
||||
virtual status_t GetAlbum(BString& album) const = 0;
|
||||
ATTR_INT64_DURATION = 'drtn'
|
||||
} Attribute;
|
||||
|
||||
virtual status_t SetTrackNumber(int32 trackNumber) = 0;
|
||||
virtual status_t GetTrackNumber(int32& trackNumber) const = 0;
|
||||
virtual status_t SetAttribute(const Attribute& attribute,
|
||||
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 GetBitRate(int32& bitRate) const = 0;
|
||||
virtual status_t SetAttribute(const Attribute& attribute,
|
||||
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
|
||||
virtual BString LocationURI() const = 0;
|
||||
virtual status_t GetIcon(BBitmap* bitmap,
|
||||
icon_size iconSize) const = 0;
|
||||
|
||||
virtual status_t MoveIntoTrash() = 0;
|
||||
virtual status_t RestoreFromTrash() = 0;
|
||||
|
||||
@ -72,4 +101,6 @@ private:
|
||||
BList fListeners;
|
||||
};
|
||||
|
||||
typedef Reference<PlaylistItem> PlaylistItemRef;
|
||||
|
||||
#endif // PLAYLIST_ITEM_H
|
||||
|
@ -1,10 +1,8 @@
|
||||
/*
|
||||
* Copyright 2007-2009, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "PlaylistListView.h"
|
||||
|
||||
#include <new>
|
||||
@ -29,6 +27,7 @@
|
||||
#include "MovePLItemsCommand.h"
|
||||
#include "PlaybackState.h"
|
||||
#include "Playlist.h"
|
||||
#include "PlaylistItem.h"
|
||||
#include "PlaylistObserver.h"
|
||||
#include "RandomizePLItemsCommand.h"
|
||||
#include "RemovePLItemsCommand.h"
|
||||
@ -56,32 +55,37 @@ text_offset(const font_height& fh)
|
||||
}
|
||||
|
||||
|
||||
class PlaylistListView::Item : public SimpleItem {
|
||||
public:
|
||||
Item(const entry_ref& ref);
|
||||
virtual ~Item();
|
||||
class PlaylistListView::Item : public SimpleItem,
|
||||
public PlaylistItem::Listener {
|
||||
public:
|
||||
Item(PlaylistItem* item);
|
||||
virtual ~Item();
|
||||
|
||||
void Draw(BView* owner, BRect frame,
|
||||
void Draw(BView* owner, BRect frame,
|
||||
const font_height& fh,
|
||||
bool tintedLine, uint32 mode,
|
||||
bool active,
|
||||
uint32 playbackState);
|
||||
|
||||
private:
|
||||
entry_ref fRef;
|
||||
virtual void ItemChanged(const PlaylistItem* item);
|
||||
|
||||
private:
|
||||
PlaylistItemRef fItem;
|
||||
|
||||
};
|
||||
|
||||
|
||||
PlaylistListView::Item::Item(const entry_ref& ref)
|
||||
: SimpleItem(ref.name),
|
||||
fRef(ref)
|
||||
PlaylistListView::Item::Item(PlaylistItem* item)
|
||||
: SimpleItem(item->Name().String()),
|
||||
fItem(item)
|
||||
{
|
||||
fItem->AddListener(this);
|
||||
}
|
||||
|
||||
|
||||
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 -
|
||||
|
||||
|
||||
@ -234,6 +245,8 @@ PlaylistListView::PlaylistListView(BRect frame, Playlist* playlist,
|
||||
|
||||
PlaylistListView::~PlaylistListView()
|
||||
{
|
||||
for (int32 i = CountItems() - 1; i >= 0; i--)
|
||||
_RemoveItem(i);
|
||||
fPlaylist->RemoveListener(fPlaylistObserver);
|
||||
delete fPlaylistObserver;
|
||||
fController->RemoveListener(fControllerObserver);
|
||||
@ -258,24 +271,27 @@ PlaylistListView::MessageReceived(BMessage* message)
|
||||
// message->PrintToStream();
|
||||
switch (message->what) {
|
||||
// PlaylistObserver messages
|
||||
case MSG_PLAYLIST_REF_ADDED: {
|
||||
entry_ref ref;
|
||||
case MSG_PLAYLIST_ITEM_ADDED:
|
||||
{
|
||||
PlaylistItem* item;
|
||||
int32 index;
|
||||
if (message->FindRef("refs", &ref) == B_OK
|
||||
if (message->FindPointer("item", (void**)&item) == B_OK
|
||||
&& message->FindInt32("index", &index) == B_OK)
|
||||
_AddItem(ref, index);
|
||||
_AddItem(item, index);
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_REF_REMOVED: {
|
||||
case MSG_PLAYLIST_ITEM_REMOVED:
|
||||
{
|
||||
int32 index;
|
||||
if (message->FindInt32("index", &index) == B_OK)
|
||||
_RemoveItem(index);
|
||||
break;
|
||||
}
|
||||
case MSG_PLAYLIST_REFS_SORTED:
|
||||
case MSG_PLAYLIST_ITEMS_SORTED:
|
||||
_FullSync();
|
||||
break;
|
||||
case MSG_PLAYLIST_CURRENT_REF_CHANGED: {
|
||||
case MSG_PLAYLIST_CURRENT_ITEM_CHANGED:
|
||||
{
|
||||
int32 index;
|
||||
if (message->FindInt32("index", &index) == B_OK)
|
||||
_SetCurrentPlaylistIndex(index);
|
||||
@ -283,7 +299,8 @@ PlaylistListView::MessageReceived(BMessage* message)
|
||||
}
|
||||
|
||||
// ControllerObserver messages
|
||||
case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED: {
|
||||
case MSG_CONTROLLER_PLAYBACK_STATE_CHANGED:
|
||||
{
|
||||
uint32 state;
|
||||
if (message->FindInt32("state", (int32*)&state) == B_OK)
|
||||
_SetPlaybackState(state);
|
||||
@ -330,7 +347,7 @@ PlaylistListView::MouseDown(BPoint where)
|
||||
// only do something if user clicked the same item twice
|
||||
if (fLastClickedItem == item) {
|
||||
BAutolock _(fPlaylist);
|
||||
fPlaylist->SetCurrentRefIndex(i);
|
||||
fPlaylist->SetCurrentItemIndex(i);
|
||||
handled = true;
|
||||
}
|
||||
} else {
|
||||
@ -486,16 +503,14 @@ PlaylistListView::_FullSync()
|
||||
scrollBar->SetTarget((BView*)NULL);
|
||||
}
|
||||
|
||||
MakeEmpty();
|
||||
for (int32 i = CountItems() - 1; i >= 0; i--)
|
||||
_RemoveItem(i);
|
||||
|
||||
int32 count = fPlaylist->CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
entry_ref ref;
|
||||
if (fPlaylist->GetRefAt(i, &ref) == B_OK)
|
||||
_AddItem(ref, i);
|
||||
}
|
||||
for (int32 i = 0; i < count; i++)
|
||||
_AddItem(fPlaylist->ItemAt(i), i);
|
||||
|
||||
_SetCurrentPlaylistIndex(fPlaylist->CurrentRefIndex());
|
||||
_SetCurrentPlaylistIndex(fPlaylist->CurrentItemIndex());
|
||||
_SetPlaybackState(fController->PlaybackState());
|
||||
|
||||
// reattach scrollbar and sync it by calling FrameResized()
|
||||
@ -509,10 +524,13 @@ PlaylistListView::_FullSync()
|
||||
|
||||
|
||||
void
|
||||
PlaylistListView::_AddItem(const entry_ref& ref, int32 index)
|
||||
PlaylistListView::_AddItem(PlaylistItem* _item, int32 index)
|
||||
{
|
||||
Item* item = new (nothrow) Item(ref);
|
||||
if (item)
|
||||
if (_item == NULL)
|
||||
return;
|
||||
|
||||
Item* item = new (nothrow) Item(_item);
|
||||
if (item != NULL)
|
||||
AddItem(item, index);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ class CommandStack;
|
||||
class Controller;
|
||||
class ControllerObserver;
|
||||
class Playlist;
|
||||
class PlaylistItem;
|
||||
class PlaylistObserver;
|
||||
|
||||
class PlaylistListView : public SimpleListView {
|
||||
@ -53,7 +54,7 @@ private:
|
||||
class Item;
|
||||
|
||||
void _FullSync();
|
||||
void _AddItem(const entry_ref& ref, int32 index);
|
||||
void _AddItem(PlaylistItem* item, int32 index);
|
||||
void _RemoveItem(int32 index);
|
||||
|
||||
void _SetCurrentPlaylistIndex(int32 index);
|
||||
|
@ -1,9 +1,6 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "PlaylistObserver.h"
|
||||
@ -24,10 +21,10 @@ PlaylistObserver::~PlaylistObserver()
|
||||
|
||||
|
||||
void
|
||||
PlaylistObserver::RefAdded(const entry_ref& ref, int32 index)
|
||||
PlaylistObserver::ItemAdded(PlaylistItem* item, int32 index)
|
||||
{
|
||||
BMessage message(MSG_PLAYLIST_REF_ADDED);
|
||||
message.AddRef("refs", &ref);
|
||||
BMessage message(MSG_PLAYLIST_ITEM_ADDED);
|
||||
message.AddPointer("item", item);
|
||||
message.AddInt32("index", index);
|
||||
|
||||
DeliverMessage(message);
|
||||
@ -35,9 +32,9 @@ PlaylistObserver::RefAdded(const entry_ref& ref, int32 index)
|
||||
|
||||
|
||||
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);
|
||||
|
||||
DeliverMessage(message);
|
||||
@ -45,18 +42,18 @@ PlaylistObserver::RefRemoved(int32 index)
|
||||
|
||||
|
||||
void
|
||||
PlaylistObserver::RefsSorted()
|
||||
PlaylistObserver::ItemsSorted()
|
||||
{
|
||||
BMessage message(MSG_PLAYLIST_REFS_SORTED);
|
||||
BMessage message(MSG_PLAYLIST_ITEMS_SORTED);
|
||||
|
||||
DeliverMessage(message);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
DeliverMessage(message);
|
||||
|
@ -1,9 +1,6 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright 2007-2009 Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PLAYLIST_OBSERVER_H
|
||||
#define PLAYLIST_OBSERVER_H
|
||||
@ -12,24 +9,23 @@
|
||||
#include "Playlist.h"
|
||||
|
||||
enum {
|
||||
MSG_PLAYLIST_REF_ADDED = 'plra',
|
||||
MSG_PLAYLIST_REF_REMOVED = 'plrr',
|
||||
MSG_PLAYLIST_REFS_SORTED = 'plrs',
|
||||
MSG_PLAYLIST_CURRENT_REF_CHANGED = 'plcc'
|
||||
MSG_PLAYLIST_ITEM_ADDED = 'plia',
|
||||
MSG_PLAYLIST_ITEM_REMOVED = 'plir',
|
||||
MSG_PLAYLIST_ITEMS_SORTED = 'plis',
|
||||
MSG_PLAYLIST_CURRENT_ITEM_CHANGED = 'plcc'
|
||||
};
|
||||
|
||||
class PlaylistObserver : public Playlist::Listener,
|
||||
public AbstractLOAdapter {
|
||||
public:
|
||||
PlaylistObserver(BHandler* target);
|
||||
virtual ~PlaylistObserver();
|
||||
class PlaylistObserver : public Playlist::Listener, public AbstractLOAdapter {
|
||||
public:
|
||||
PlaylistObserver(BHandler* target);
|
||||
virtual ~PlaylistObserver();
|
||||
|
||||
virtual void RefAdded(const entry_ref& ref, int32 index);
|
||||
virtual void RefRemoved(int32 index);
|
||||
virtual void ItemAdded(PlaylistItem* item, 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2008 Stephan Aßmus. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
* Copyright © 2008-2009 Stephan Aßmus <superstippi@gmx.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "RandomizePLItemsCommand.h"
|
||||
@ -19,31 +19,33 @@ using std::nothrow;
|
||||
|
||||
RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
|
||||
const int32* indices, int32 count)
|
||||
: Command()
|
||||
, fPlaylist(playlist)
|
||||
, fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL)
|
||||
, fListIndices(count > 0 ? new (nothrow) int32[count] : NULL)
|
||||
, fRandomInternalIndices(count > 0 ? new (nothrow) int32[count] : NULL)
|
||||
, fCount(count)
|
||||
:
|
||||
PLItemsCommand(),
|
||||
fPlaylist(playlist),
|
||||
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
|
||||
fListIndices(count > 0 ? new (nothrow) int32[count] : NULL),
|
||||
fRandomInternalIndices(count > 0 ? new (nothrow) int32[count] : NULL),
|
||||
fCount(count)
|
||||
{
|
||||
if (!indices || !fPlaylist || !fRefs || !fListIndices
|
||||
if (!indices || !fPlaylist || !fItems || !fListIndices
|
||||
|| !fRandomInternalIndices) {
|
||||
// indicate a bad object state
|
||||
delete[] fRefs;
|
||||
fRefs = NULL;
|
||||
delete[] fItems;
|
||||
fItems = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(fListIndices, indices, fCount * sizeof(int32));
|
||||
memset(fItems, 0, fCount * sizeof(PlaylistItem*));
|
||||
|
||||
// put the available indices into a "set"
|
||||
BList indexSet;
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
if (fPlaylist->GetRefAt(fListIndices[i], &fRefs[i]) < B_OK
|
||||
|| !indexSet.AddItem((void*)i)) {
|
||||
fItems[i] = fPlaylist->ItemAt(fListIndices[i]);
|
||||
if (fItems[i] == NULL || !indexSet.AddItem((void*)i)) {
|
||||
// indicate a bad object state
|
||||
delete[] fRefs;
|
||||
fRefs = NULL;
|
||||
delete[] fItems;
|
||||
fItems = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -58,7 +60,7 @@ RandomizePLItemsCommand::RandomizePLItemsCommand(Playlist* playlist,
|
||||
|
||||
RandomizePLItemsCommand::~RandomizePLItemsCommand()
|
||||
{
|
||||
delete[] fRefs;
|
||||
delete[] fItems;
|
||||
delete[] fListIndices;
|
||||
delete[] fRandomInternalIndices;
|
||||
}
|
||||
@ -67,7 +69,7 @@ RandomizePLItemsCommand::~RandomizePLItemsCommand()
|
||||
status_t
|
||||
RandomizePLItemsCommand::InitCheck()
|
||||
{
|
||||
if (!fRefs)
|
||||
if (!fItems)
|
||||
return B_NO_INIT;
|
||||
|
||||
return B_OK;
|
||||
@ -100,36 +102,34 @@ RandomizePLItemsCommand::_Sort(bool random)
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
// remember currently playling ref in case we move it
|
||||
entry_ref currentRef;
|
||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
||||
¤tRef) == B_OK;
|
||||
// remember currently playling item in case we move it
|
||||
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||
|
||||
// remove refs from playlist
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
// "- i" to account for the items already removed
|
||||
fPlaylist->RemoveRef(fListIndices[i] - i, false);
|
||||
fPlaylist->RemoveItem(fListIndices[i] - i, false);
|
||||
}
|
||||
|
||||
// add refs to playlist at the randomized indices
|
||||
if (random) {
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
if (!fPlaylist->AddRef(fRefs[fRandomInternalIndices[i]],
|
||||
if (!fPlaylist->AddItem(fItems[fRandomInternalIndices[i]],
|
||||
fListIndices[i])) {
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// take care about currently played ref
|
||||
if (adjustCurrentRef)
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
||||
// take care about currently played item
|
||||
if (current != NULL)
|
||||
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -1,24 +1,21 @@
|
||||
/*
|
||||
* Copyright © 2008 Stephan Aßmus. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
* Copyright © 2008-2009 Stephan Aßmus <superstippi@gmx.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef RANDOMIZE_PL_ITEMS_COMMAND_H
|
||||
#define RANDOMIZE_PL_ITEMS_COMMAND_H
|
||||
|
||||
|
||||
#include "Command.h"
|
||||
#include "PLItemsCommand.h"
|
||||
|
||||
class Playlist;
|
||||
struct entry_ref;
|
||||
|
||||
class RandomizePLItemsCommand : public Command {
|
||||
public:
|
||||
class RandomizePLItemsCommand : public PLItemsCommand {
|
||||
public:
|
||||
RandomizePLItemsCommand(
|
||||
Playlist* playlist,
|
||||
const int32* indices,
|
||||
int32 count);
|
||||
virtual ~RandomizePLItemsCommand();
|
||||
|
||||
|
||||
virtual status_t InitCheck();
|
||||
|
||||
virtual status_t Perform();
|
||||
@ -26,11 +23,11 @@ class RandomizePLItemsCommand : public Command {
|
||||
|
||||
virtual void GetName(BString& name);
|
||||
|
||||
private:
|
||||
private:
|
||||
status_t _Sort(bool random);
|
||||
|
||||
Playlist* fPlaylist;
|
||||
entry_ref* fRefs;
|
||||
PlaylistItem** fItems;
|
||||
int32* fListIndices;
|
||||
int32* fRandomInternalIndices;
|
||||
int32 fCount;
|
||||
|
@ -1,9 +1,6 @@
|
||||
/*
|
||||
* Copyright 2007-2009, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright © 2007-2009 Stephan Aßmus <superstippi@gmx.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "RemovePLItemsCommand.h"
|
||||
@ -13,10 +10,6 @@
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Autolock.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include "Playlist.h"
|
||||
|
||||
@ -27,35 +20,31 @@ using std::nothrow;
|
||||
RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist,
|
||||
const int32* indices, int32 count, bool moveFilesToTrash)
|
||||
:
|
||||
Command(),
|
||||
PLItemsCommand(),
|
||||
fPlaylist(playlist),
|
||||
fRefs(count > 0 ? new (nothrow) entry_ref[count] : NULL),
|
||||
fNamesInTrash(NULL),
|
||||
fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL),
|
||||
fIndices(count > 0 ? new (nothrow) int32[count] : NULL),
|
||||
fCount(count),
|
||||
fMoveFilesToTrash(moveFilesToTrash),
|
||||
fMoveErrorShown(false)
|
||||
fMoveErrorShown(false),
|
||||
fItemsRemoved(false)
|
||||
{
|
||||
if (!indices || !fPlaylist || !fRefs || !fIndices) {
|
||||
if (!indices || !fPlaylist || !fItems || !fIndices) {
|
||||
// indicate a bad object state
|
||||
delete[] fRefs;
|
||||
fRefs = NULL;
|
||||
delete[] fItems;
|
||||
fItems = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(fIndices, indices, fCount * sizeof(int32));
|
||||
|
||||
if (fMoveFilesToTrash) {
|
||||
fNamesInTrash = new (nothrow) BString[count];
|
||||
if (fNamesInTrash == NULL)
|
||||
return;
|
||||
}
|
||||
memset(fItems, 0, fCount * sizeof(PlaylistItem*));
|
||||
|
||||
// init original entry indices
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
if (fPlaylist->GetRefAt(fIndices[i], &fRefs[i]) < B_OK) {
|
||||
delete[] fRefs;
|
||||
fRefs = NULL;
|
||||
fItems[i] = fPlaylist->ItemAt(fIndices[i]);
|
||||
if (fItems[i] == NULL) {
|
||||
delete[] fItems;
|
||||
fItems = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -64,19 +53,16 @@ RemovePLItemsCommand::RemovePLItemsCommand(Playlist* playlist,
|
||||
|
||||
RemovePLItemsCommand::~RemovePLItemsCommand()
|
||||
{
|
||||
delete[] fRefs;
|
||||
_CleanUp(fItems, fCount, fItemsRemoved);
|
||||
delete[] fIndices;
|
||||
delete[] fNamesInTrash;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RemovePLItemsCommand::InitCheck()
|
||||
{
|
||||
if (!fPlaylist || !fRefs || !fIndices
|
||||
|| (fMoveFilesToTrash && !fNamesInTrash)) {
|
||||
if (!fPlaylist || !fItems || !fIndices)
|
||||
return B_NO_INIT;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -86,65 +72,32 @@ RemovePLItemsCommand::Perform()
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
fItemsRemoved = true;
|
||||
|
||||
int32 lastRemovedIndex = -1;
|
||||
|
||||
// remove refs from playlist
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
// "- i" to account for the items already removed
|
||||
lastRemovedIndex = fIndices[i] - i;
|
||||
fPlaylist->RemoveRef(lastRemovedIndex);
|
||||
fPlaylist->RemoveItem(lastRemovedIndex);
|
||||
}
|
||||
|
||||
// in case we removed the currently playing file
|
||||
if (fPlaylist->CurrentRefIndex() == -1)
|
||||
fPlaylist->SetCurrentRefIndex(lastRemovedIndex);
|
||||
if (fPlaylist->CurrentItemIndex() == -1)
|
||||
fPlaylist->SetCurrentItemIndex(lastRemovedIndex);
|
||||
|
||||
if (fMoveFilesToTrash) {
|
||||
BString errorFiles;
|
||||
status_t moveError = B_OK;
|
||||
bool errorOnAllFiles = true;
|
||||
char trashPath[B_PATH_NAME_LENGTH];
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
status_t err = find_directory(B_TRASH_DIRECTORY, fRefs[i].device,
|
||||
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());
|
||||
status_t err = fItems[i]->MoveIntoTrash();
|
||||
if (err != B_OK) {
|
||||
moveError = err;
|
||||
if (errorFiles.Length() > 0)
|
||||
errorFiles << ' ';
|
||||
errorFiles << fRefs[i].name;
|
||||
errorFiles << fItems[i]->Name();
|
||||
} else
|
||||
errorOnAllFiles = false;
|
||||
}
|
||||
@ -173,61 +126,21 @@ RemovePLItemsCommand::Undo()
|
||||
{
|
||||
BAutolock _(fPlaylist);
|
||||
|
||||
status_t ret = B_OK;
|
||||
fItemsRemoved = false;
|
||||
|
||||
if (fMoveFilesToTrash) {
|
||||
char trashPath[B_PATH_NAME_LENGTH];
|
||||
for (int32 i = 0; i < fCount; i++) {
|
||||
status_t err = find_directory(B_TRASH_DIRECTORY, fRefs[i].device,
|
||||
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;
|
||||
fItems[i]->RestoreFromTrash();
|
||||
}
|
||||
}
|
||||
|
||||
// remember currently playling ref in case we move it
|
||||
entry_ref currentRef;
|
||||
bool adjustCurrentRef = fPlaylist->GetRefAt(fPlaylist->CurrentRefIndex(),
|
||||
¤tRef) == B_OK;
|
||||
// remember currently playling item in case we move it
|
||||
PlaylistItem* current = fPlaylist->ItemAt(fPlaylist->CurrentItemIndex());
|
||||
|
||||
// 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++) {
|
||||
if (!fPlaylist->AddRef(fRefs[i], fIndices[i])) {
|
||||
if (!fPlaylist->AddItem(fItems[i], fIndices[i])) {
|
||||
ret = B_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
@ -236,8 +149,8 @@ BEntry entry(path.Path());
|
||||
return ret;
|
||||
|
||||
// take care about currently played ref
|
||||
if (adjustCurrentRef)
|
||||
fPlaylist->SetCurrentRefIndex(fPlaylist->IndexOf(currentRef));
|
||||
if (current != NULL)
|
||||
fPlaylist->SetCurrentItemIndex(fPlaylist->IndexOf(current));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -1,21 +1,15 @@
|
||||
/*
|
||||
* Copyright 2007-2009, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright © 2007-2009 Stephan Aßmus <superstippi@gmx.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef REMOVE_PL_ITEMS_COMMAND_H
|
||||
#define REMOVE_PL_ITEMS_COMMAND_H
|
||||
|
||||
|
||||
#include "Command.h"
|
||||
#include "PLItemsCommand.h"
|
||||
|
||||
struct entry_ref;
|
||||
class Playlist;
|
||||
|
||||
class RemovePLItemsCommand : public Command {
|
||||
public:
|
||||
class RemovePLItemsCommand : public PLItemsCommand {
|
||||
public:
|
||||
RemovePLItemsCommand(
|
||||
Playlist* playlist,
|
||||
const int32* indices,
|
||||
@ -30,14 +24,14 @@ class RemovePLItemsCommand : public Command {
|
||||
|
||||
virtual void GetName(BString& name);
|
||||
|
||||
private:
|
||||
private:
|
||||
Playlist* fPlaylist;
|
||||
entry_ref* fRefs;
|
||||
BString* fNamesInTrash;
|
||||
PlaylistItem** fItems;
|
||||
int32* fIndices;
|
||||
int32 fCount;
|
||||
bool fMoveFilesToTrash;
|
||||
bool fMoveErrorShown;
|
||||
bool fItemsRemoved;
|
||||
};
|
||||
|
||||
#endif // REMOVE_PL_ITEMS_COMMAND_H
|
||||
|
@ -17,7 +17,7 @@ using namespace std;
|
||||
|
||||
//#define TRACE_AUDIO_SUPPLIER
|
||||
#ifdef TRACE_AUDIO_SUPPLIER
|
||||
# define TRACE(x...) printf("MediaTrackAudioSupplier::"); printf(x)
|
||||
# define TRACE(x...) printf("MediaTrackAudioSupplier::" x)
|
||||
#else
|
||||
# define TRACE(x...)
|
||||
#endif
|
||||
@ -123,6 +123,8 @@ MediaTrackAudioSupplier::Read(void* buffer, int64 pos, int64 frames)
|
||||
frames);
|
||||
TRACE(" this: %p, fOutOffset: %lld\n", this, fOutOffset);
|
||||
|
||||
//printf("MediaTrackAudioSupplier::Read(%p, %lld, %lld)\n", buffer, pos, frames);
|
||||
|
||||
status_t error = InitCheck();
|
||||
if (error != B_OK) {
|
||||
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",
|
||||
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
|
||||
bigtime_t time = system_time();
|
||||
if (frames > 0)
|
||||
@ -152,6 +206,7 @@ MediaTrackAudioSupplier::Read(void* buffer, int64 pos, int64 frames)
|
||||
if (frames > 0)
|
||||
_ReadUncachedFrames(buffer, pos, frames, time);
|
||||
|
||||
#endif
|
||||
TRACE("Read() done\n");
|
||||
|
||||
return B_OK;
|
||||
@ -203,6 +258,8 @@ MediaTrackAudioSupplier::_InitFromTrack()
|
||||
|
||||
TRACE("MediaTrackAudioSupplier: keyframes: %d, frame count: %lld\n",
|
||||
fHasKeyFrames, fCountFrames);
|
||||
printf("MediaTrackAudioSupplier: keyframes: %d, frame count: %lld\n",
|
||||
fHasKeyFrames, fCountFrames);
|
||||
} else
|
||||
fMediaTrack = NULL;
|
||||
}
|
||||
@ -416,19 +473,6 @@ MediaTrackAudioSupplier::_ReadBuffer(Buffer* buffer, int64 position,
|
||||
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
|
||||
//
|
||||
// Tries to read as much as possible data from the cache. The supplied
|
||||
@ -454,8 +498,8 @@ MediaTrackAudioSupplier::_ReadCachedFrames(void*& dest, int64& pos,
|
||||
pos += size;
|
||||
frames -= 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
|
||||
// much data from the end as possible.
|
||||
@ -469,23 +513,11 @@ MediaTrackAudioSupplier::_ReadCachedFrames(void*& dest, int64& pos,
|
||||
_CopyFrames(buffer->data, buffer->offset, dest, pos,
|
||||
pos + frames - size, 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
|
||||
//
|
||||
// Reads /frames/ frames from /position/ into /buffer/. The frames are not
|
||||
@ -521,8 +553,10 @@ MediaTrackAudioSupplier::_ReadUncachedFrames(void* buffer, int64 position,
|
||||
currentPos += cacheBuffer->size;
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
// 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) {
|
||||
int64 nextKeyFrame = currentPos;
|
||||
if (_FindKeyFrameForward(nextKeyFrame) == B_OK) {
|
||||
@ -540,6 +574,8 @@ MediaTrackAudioSupplier::_ReadUncachedFrames(void* buffer, int64 position,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// on error fill up the buffer with silence
|
||||
if (error != B_OK && frames > 0)
|
||||
ReadSilence(buffer, frames);
|
||||
@ -551,17 +587,17 @@ status_t
|
||||
MediaTrackAudioSupplier::_FindKeyFrameForward(int64& position)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
// NOTE: the keyframe version confuses the Frauenhofer MP3 decoder,
|
||||
// it works fine with the non-keyframe version, so let's hope this
|
||||
// is the case for all other keyframe based BeOS codecs...
|
||||
// if (fHasKeyFrames) {
|
||||
// error = fMediaTrack->FindKeyFrameForFrame(
|
||||
// &position, B_MEDIA_SEEK_CLOSEST_FORWARD);
|
||||
// } else {
|
||||
#ifdef __HAIKU__
|
||||
if (fHasKeyFrames) {
|
||||
error = fMediaTrack->FindKeyFrameForFrame(
|
||||
&position, B_MEDIA_SEEK_CLOSEST_FORWARD);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
int64 framesPerBuffer = _FramesPerBuffer();
|
||||
position += framesPerBuffer - 1;
|
||||
position = position % framesPerBuffer;
|
||||
// }
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -578,6 +614,7 @@ MediaTrackAudioSupplier::_FindKeyFrameBackward(int64& position)
|
||||
return error;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// _SeekToKeyFrameForward
|
||||
status_t
|
||||
MediaTrackAudioSupplier::_SeekToKeyFrameForward(int64& position)
|
||||
@ -601,6 +638,7 @@ MediaTrackAudioSupplier::_SeekToKeyFrameForward(int64& position)
|
||||
}
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
// _SeekToKeyFrameBackward
|
||||
status_t
|
||||
@ -614,16 +652,16 @@ MediaTrackAudioSupplier::_SeekToKeyFrameBackward(int64& position)
|
||||
int64 oldPosition = position;
|
||||
error = fMediaTrack->FindKeyFrameForFrame(&position,
|
||||
B_MEDIA_SEEK_CLOSEST_BACKWARD);
|
||||
if (error >= B_OK)
|
||||
if (error == B_OK)
|
||||
error = fMediaTrack->SeekToFrame(&position, 0);
|
||||
if (error < B_OK) {
|
||||
if (error != B_OK) {
|
||||
position = fMediaTrack->CurrentFrame();
|
||||
if (fReportSeekError) {
|
||||
// if (fReportSeekError) {
|
||||
printf(" seek to key frame backward: %lld -> %lld (%lld) "
|
||||
"- %s\n", oldPosition, position,
|
||||
fMediaTrack->CurrentFrame(), strerror(error));
|
||||
fReportSeekError = false;
|
||||
}
|
||||
// }
|
||||
} else {
|
||||
fReportSeekError = true;
|
||||
}
|
||||
|
@ -62,21 +62,18 @@ class MediaTrackAudioSupplier : public AudioTrackSupplier {
|
||||
status_t _ReadBuffer(Buffer* buffer, int64 position,
|
||||
bigtime_t time);
|
||||
|
||||
void _ReadCachedFrames(void*& buffer,
|
||||
int64& position, int64& frames);
|
||||
void _ReadCachedFrames(void*& buffer,
|
||||
int64& position, int64& frames,
|
||||
bigtime_t time);
|
||||
|
||||
status_t _ReadUncachedFrames(void* buffer,
|
||||
int64 position, int64 frames);
|
||||
status_t _ReadUncachedFrames(void* buffer,
|
||||
int64 position, int64 frames,
|
||||
bigtime_t time);
|
||||
|
||||
status_t _FindKeyFrameForward(int64& position);
|
||||
status_t _FindKeyFrameBackward(int64& position);
|
||||
status_t _SeekToKeyFrameForward(int64& position);
|
||||
// NOTE: unused
|
||||
// status_t _SeekToKeyFrameForward(int64& position);
|
||||
status_t _SeekToKeyFrameBackward(int64& position);
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user