diff --git a/src/apps/mediaplayer/Controller.cpp b/src/apps/mediaplayer/Controller.cpp index f273f0a8bc..0113b57b13 100644 --- a/src/apps/mediaplayer/Controller.cpp +++ b/src/apps/mediaplayer/Controller.cpp @@ -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 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 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; } diff --git a/src/apps/mediaplayer/Controller.h b/src/apps/mediaplayer/Controller.h index 848c8d3e82..1da8d4f891 100644 --- a/src/apps/mediaplayer/Controller.h +++ b/src/apps/mediaplayer/Controller.h @@ -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; }; diff --git a/src/apps/mediaplayer/ControllerView.cpp b/src/apps/mediaplayer/ControllerView.cpp index 84cf06f50a..b6f76b6ffe 100644 --- a/src/apps/mediaplayer/ControllerView.cpp +++ b/src/apps/mediaplayer/ControllerView.cpp @@ -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); } diff --git a/src/apps/mediaplayer/InfoWin.cpp b/src/apps/mediaplayer/InfoWin.cpp index fd50572984..4c3359181d 100644 --- a/src/apps/mediaplayer/InfoWin.cpp +++ b/src/apps/mediaplayer/InfoWin.cpp @@ -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(); } diff --git a/src/apps/mediaplayer/Jamfile b/src/apps/mediaplayer/Jamfile index 371bd0faa3..4481267e19 100644 --- a/src/apps/mediaplayer/Jamfile +++ b/src/apps/mediaplayer/Jamfile @@ -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 diff --git a/src/apps/mediaplayer/MainWin.cpp b/src/apps/mediaplayer/MainWin.cpp index 6aac2cedda..e1bfafa5c6 100644 --- a/src/apps/mediaplayer/MainWin.cpp +++ b/src/apps/mediaplayer/MainWin.cpp @@ -2,7 +2,7 @@ * MainWin.cpp - Media Player for the Haiku Operating System * * Copyright (C) 2006 Marcus Overhagen - * Copyright (C) 2007-2008 Stephan Aßmus (GPL->MIT ok) + * Copyright (C) 2007-2009 Stephan Aßmus (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 @@ -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); } diff --git a/src/apps/mediaplayer/MainWin.h b/src/apps/mediaplayer/MainWin.h index 88f0fc68a8..3261fd1de2 100644 --- a/src/apps/mediaplayer/MainWin.h +++ b/src/apps/mediaplayer/MainWin.h @@ -2,7 +2,7 @@ * MainWin.h - Media Player for the Haiku Operating System * * Copyright (C) 2006 Marcus Overhagen - * Copyright (C) 2007 Stephan Aßmus + * Copyright (C) 2007-2009 Stephan Aßmus (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; diff --git a/src/apps/mediaplayer/playlist/CopyPLItemsCommand.cpp b/src/apps/mediaplayer/playlist/CopyPLItemsCommand.cpp index f3ca795742..d80b4892d1 100644 --- a/src/apps/mediaplayer/playlist/CopyPLItemsCommand.cpp +++ b/src/apps/mediaplayer/playlist/CopyPLItemsCommand.cpp @@ -1,11 +1,7 @@ /* - * Copyright 2007, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright © 2007-2009 Stephan Aßmus . + * All rights reserved. Distributed under the terms of the MIT License. */ - #include "CopyPLItemsCommand.h" #include @@ -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; } diff --git a/src/apps/mediaplayer/playlist/CopyPLItemsCommand.h b/src/apps/mediaplayer/playlist/CopyPLItemsCommand.h index 099c8c6d5b..7d9b6c4c24 100644 --- a/src/apps/mediaplayer/playlist/CopyPLItemsCommand.h +++ b/src/apps/mediaplayer/playlist/CopyPLItemsCommand.h @@ -1,28 +1,22 @@ /* - * Copyright 2007, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright © 2007-2009 Stephan Aßmus . + * 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 diff --git a/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.cpp b/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.cpp deleted file mode 100644 index ce27e1cbd4..0000000000 --- a/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2009 Stephan Aßmus - * All rights reserved. Distributed under the terms of the MIT license. - */ - -#include "EntryRefPlaylistItem.h" - -#include - -#include - - -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); -} - diff --git a/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.h b/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.h deleted file mode 100644 index 442dec3565..0000000000 --- a/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2009 Stephan Aßmus - * 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 - -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 diff --git a/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp b/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp new file mode 100644 index 0000000000..edb5b212ae --- /dev/null +++ b/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp @@ -0,0 +1,300 @@ +/* + * Copyright © 2009 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "FilePlaylistItem.h" + +#include + +#include + +#include +#include +#include +#include +#include + + +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); +} + diff --git a/src/apps/mediaplayer/playlist/FilePlaylistItem.h b/src/apps/mediaplayer/playlist/FilePlaylistItem.h new file mode 100644 index 0000000000..725c94007f --- /dev/null +++ b/src/apps/mediaplayer/playlist/FilePlaylistItem.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2009 Stephan Aßmus + * 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 + +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 diff --git a/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp b/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp index 64c97ae65d..968d4884bb 100644 --- a/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp +++ b/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp @@ -1,9 +1,6 @@ /* - * Copyright 2007, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright 2007-2009 Stephan Aßmus . + * All rights reserved. Distributed under the terms of the MIT License. */ #include "ImportPLItemsCommand.h" @@ -15,6 +12,7 @@ #include #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"; } + diff --git a/src/apps/mediaplayer/playlist/ImportPLItemsCommand.h b/src/apps/mediaplayer/playlist/ImportPLItemsCommand.h index 9d22726543..f4cc895000 100644 --- a/src/apps/mediaplayer/playlist/ImportPLItemsCommand.h +++ b/src/apps/mediaplayer/playlist/ImportPLItemsCommand.h @@ -1,28 +1,23 @@ /* - * Copyright 2007, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright 2007-2009 Stephan Aßmus . + * 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 diff --git a/src/apps/mediaplayer/playlist/MovePLItemsCommand.cpp b/src/apps/mediaplayer/playlist/MovePLItemsCommand.cpp index 554875e458..82db05433d 100644 --- a/src/apps/mediaplayer/playlist/MovePLItemsCommand.cpp +++ b/src/apps/mediaplayer/playlist/MovePLItemsCommand.cpp @@ -1,9 +1,6 @@ /* - * Copyright 2007, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright 2007-2009 Stephan Aßmus . + * 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; } diff --git a/src/apps/mediaplayer/playlist/MovePLItemsCommand.h b/src/apps/mediaplayer/playlist/MovePLItemsCommand.h index f093dd54c8..d79031deb3 100644 --- a/src/apps/mediaplayer/playlist/MovePLItemsCommand.h +++ b/src/apps/mediaplayer/playlist/MovePLItemsCommand.h @@ -1,20 +1,14 @@ /* - * Copyright 2007, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright 2007-2009 Stephan Aßmus . + * 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; diff --git a/src/apps/mediaplayer/playlist/PLItemsCommand.cpp b/src/apps/mediaplayer/playlist/PLItemsCommand.cpp new file mode 100644 index 0000000000..d7ac2041bc --- /dev/null +++ b/src/apps/mediaplayer/playlist/PLItemsCommand.cpp @@ -0,0 +1,41 @@ +/* + * Copyright 2009 Stephan Aßmus . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "PLItemsCommand.h" + +#include + +#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; +} + diff --git a/src/apps/mediaplayer/playlist/PLItemsCommand.h b/src/apps/mediaplayer/playlist/PLItemsCommand.h new file mode 100644 index 0000000000..ce592b5af8 --- /dev/null +++ b/src/apps/mediaplayer/playlist/PLItemsCommand.h @@ -0,0 +1,24 @@ +/* + * Copyright 2009 Stephan Aßmus . + * 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 diff --git a/src/apps/mediaplayer/playlist/Playlist.cpp b/src/apps/mediaplayer/playlist/Playlist.cpp index 5066ca4495..2201541dbd 100644 --- a/src/apps/mediaplayer/playlist/Playlist.cpp +++ b/src/apps/mediaplayer/playlist/Playlist.cpp @@ -2,8 +2,8 @@ * Playlist.cpp - Media Player for the Haiku Operating System * * Copyright (C) 2006 Marcus Overhagen - * Copyright (C) 2007 Stephan Aßmus - * Copyright (C) 2008-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok) + * Copyright (C) 2007-2009 Stephan Aßmus (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 #include #include +#include +#include #include #include +#include #include #include #include #include #include +#include #include +#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(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); } } diff --git a/src/apps/mediaplayer/playlist/Playlist.h b/src/apps/mediaplayer/playlist/Playlist.h index 7efdc06e0e..204b6a0c4d 100644 --- a/src/apps/mediaplayer/playlist/Playlist.h +++ b/src/apps/mediaplayer/playlist/Playlist.h @@ -2,8 +2,8 @@ * Playlist.h - Media Player for the Haiku Operating System * * Copyright (C) 2006 Marcus Overhagen - * Copyright (C) 2007 Stephan Aßmus - * Copyright (C) 2008-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok) + * Copyright (C) 2007-2009 Stephan Aßmus (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 #include #include +#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; diff --git a/src/apps/mediaplayer/playlist/PlaylistItem.cpp b/src/apps/mediaplayer/playlist/PlaylistItem.cpp index 0334ca7bda..73918553dc 100644 --- a/src/apps/mediaplayer/playlist/PlaylistItem.cpp +++ b/src/apps/mediaplayer/playlist/PlaylistItem.cpp @@ -5,6 +5,8 @@ #include "PlaylistItem.h" +#include + 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 = ""; + return name; +} + + +BString +PlaylistItem::Author() const +{ + BString author; + if (GetAttribute(ATTR_STRING_AUTHOR, author) != B_OK) + author = ""; + return author; +} + + +BString +PlaylistItem::Album() const +{ + BString album; + if (GetAttribute(ATTR_STRING_ALBUM, album) != B_OK) + album = ""; + return album; +} + + +BString +PlaylistItem::Title() const +{ + BString title; + if (GetAttribute(ATTR_STRING_TITLE, title) != B_OK) + title = ""; + 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; } diff --git a/src/apps/mediaplayer/playlist/PlaylistItem.h b/src/apps/mediaplayer/playlist/PlaylistItem.h index 0be9b0040c..71f775b83c 100644 --- a/src/apps/mediaplayer/playlist/PlaylistItem.h +++ b/src/apps/mediaplayer/playlist/PlaylistItem.h @@ -5,14 +5,18 @@ #ifndef PLAYLIST_ITEM_H #define PLAYLIST_ITEM_H +#include #include +#include +#include #include +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 PlaylistItemRef; + #endif // PLAYLIST_ITEM_H diff --git a/src/apps/mediaplayer/playlist/PlaylistListView.cpp b/src/apps/mediaplayer/playlist/PlaylistListView.cpp index 5b2857e023..e6f363cfdc 100644 --- a/src/apps/mediaplayer/playlist/PlaylistListView.cpp +++ b/src/apps/mediaplayer/playlist/PlaylistListView.cpp @@ -1,10 +1,8 @@ /* - * Copyright 2007-2009, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright 2007-2009 Stephan Aßmus . + * All rights reserved. Distributed under the terms of the MIT License. */ + #include "PlaylistListView.h" #include @@ -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); } diff --git a/src/apps/mediaplayer/playlist/PlaylistListView.h b/src/apps/mediaplayer/playlist/PlaylistListView.h index 98a3fd0690..7696a9bcf0 100644 --- a/src/apps/mediaplayer/playlist/PlaylistListView.h +++ b/src/apps/mediaplayer/playlist/PlaylistListView.h @@ -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); diff --git a/src/apps/mediaplayer/playlist/PlaylistObserver.cpp b/src/apps/mediaplayer/playlist/PlaylistObserver.cpp index 33029e6039..7dfa163060 100644 --- a/src/apps/mediaplayer/playlist/PlaylistObserver.cpp +++ b/src/apps/mediaplayer/playlist/PlaylistObserver.cpp @@ -1,9 +1,6 @@ /* - * Copyright 2007, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright 2007-2009 Stephan Aßmus . + * 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); diff --git a/src/apps/mediaplayer/playlist/PlaylistObserver.h b/src/apps/mediaplayer/playlist/PlaylistObserver.h index a34d5edfd7..a594fa73fb 100644 --- a/src/apps/mediaplayer/playlist/PlaylistObserver.h +++ b/src/apps/mediaplayer/playlist/PlaylistObserver.h @@ -1,9 +1,6 @@ /* - * Copyright 2007, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright 2007-2009 Stephan Aßmus . + * 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 diff --git a/src/apps/mediaplayer/playlist/RandomizePLItemsCommand.cpp b/src/apps/mediaplayer/playlist/RandomizePLItemsCommand.cpp index 49db05a835..b3337fc0b3 100644 --- a/src/apps/mediaplayer/playlist/RandomizePLItemsCommand.cpp +++ b/src/apps/mediaplayer/playlist/RandomizePLItemsCommand.cpp @@ -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 + * 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; } diff --git a/src/apps/mediaplayer/playlist/RandomizePLItemsCommand.h b/src/apps/mediaplayer/playlist/RandomizePLItemsCommand.h index 63ff18c259..1da3fce675 100644 --- a/src/apps/mediaplayer/playlist/RandomizePLItemsCommand.h +++ b/src/apps/mediaplayer/playlist/RandomizePLItemsCommand.h @@ -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 + * 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; diff --git a/src/apps/mediaplayer/playlist/RemovePLItemsCommand.cpp b/src/apps/mediaplayer/playlist/RemovePLItemsCommand.cpp index b446b1f44c..7569248c26 100644 --- a/src/apps/mediaplayer/playlist/RemovePLItemsCommand.cpp +++ b/src/apps/mediaplayer/playlist/RemovePLItemsCommand.cpp @@ -1,9 +1,6 @@ /* - * Copyright 2007-2009, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright © 2007-2009 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT license. */ #include "RemovePLItemsCommand.h" @@ -13,10 +10,6 @@ #include #include -#include -#include -#include -#include #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; } diff --git a/src/apps/mediaplayer/playlist/RemovePLItemsCommand.h b/src/apps/mediaplayer/playlist/RemovePLItemsCommand.h index b7870fd4f7..e0ce4b6805 100644 --- a/src/apps/mediaplayer/playlist/RemovePLItemsCommand.h +++ b/src/apps/mediaplayer/playlist/RemovePLItemsCommand.h @@ -1,21 +1,15 @@ /* - * Copyright 2007-2009, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Stephan Aßmus + * Copyright © 2007-2009 Stephan Aßmus + * 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 diff --git a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp index f57048647d..e791db799f 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp +++ b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.cpp @@ -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; } diff --git a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h index abb76d4331..770d8d5223 100644 --- a/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h +++ b/src/apps/mediaplayer/supplier/MediaTrackAudioSupplier.h @@ -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: