diff --git a/src/apps/mediaplayer/Jamfile b/src/apps/mediaplayer/Jamfile index 9300dea1c3..ea96e4ce8a 100644 --- a/src/apps/mediaplayer/Jamfile +++ b/src/apps/mediaplayer/Jamfile @@ -55,10 +55,12 @@ Application MediaPlayer : # playlist CopyPLItemsCommand.cpp + EntryRefPlaylistItem.cpp ImportPLItemsCommand.cpp ListViews.cpp MovePLItemsCommand.cpp Playlist.cpp + PlaylistItem.cpp PlaylistListView.cpp PlaylistObserver.cpp PlaylistWindow.cpp diff --git a/src/apps/mediaplayer/MainWin.cpp b/src/apps/mediaplayer/MainWin.cpp index 05a27c4b64..204ad85a97 100644 --- a/src/apps/mediaplayer/MainWin.cpp +++ b/src/apps/mediaplayer/MainWin.cpp @@ -194,6 +194,11 @@ MainWin::MainWin() Settings::Default()->AddListener(&fGlobalSettingsListener); _AdoptGlobalSettings(); + AddShortcut('z', B_COMMAND_KEY, new BMessage(B_UNDO)); + AddShortcut('y', B_COMMAND_KEY, new BMessage(B_UNDO)); + AddShortcut('z', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(B_REDO)); + AddShortcut('y', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(B_REDO)); + Show(); } @@ -358,6 +363,11 @@ MainWin::MessageReceived(BMessage *msg) } break; + case B_UNDO: + case B_REDO: + fPlaylistWindow->PostMessage(msg); + break; + case M_MEDIA_SERVER_STARTED: printf("TODO: implement M_MEDIA_SERVER_STARTED\n"); // fController->... @@ -404,6 +414,8 @@ MainWin::MessageReceived(BMessage *msg) // ControllerObserver messages case MSG_CONTROLLER_FILE_FINISHED: { + BAutolock _(fPlaylist); + bool hadNext = fPlaylist->SetCurrentRefIndex( fPlaylist->CurrentRefIndex() + 1); if (!hadNext) { @@ -653,6 +665,8 @@ MainWin::MessageReceived(BMessage *msg) } */ case M_SET_PLAYLIST_POSITION: { + BAutolock _(fPlaylist); + int32 index; if (msg->FindInt32("index", &index) == B_OK) fPlaylist->SetCurrentRefIndex(index); @@ -723,6 +737,7 @@ MainWin::OpenFile(const entry_ref &ref) status_t err = fController->SetTo(ref); 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; @@ -778,10 +793,17 @@ void MainWin::ShowPlaylistWindow() { if (fPlaylistWindow->Lock()) { + // make sure the window shows on the same workspace as ourself + uint32 workspaces = Workspaces(); + if (fPlaylistWindow->Workspaces() != workspaces) + fPlaylistWindow->SetWorkspaces(workspaces); + + // show or activate if (fPlaylistWindow->IsHidden()) fPlaylistWindow->Show(); else fPlaylistWindow->Activate(); + fPlaylistWindow->Unlock(); } } @@ -823,6 +845,7 @@ MainWin::_RefsReceived(BMessage* msg) // the playlist ist replaced by dropped files // or the dropped files are appended to the end // of the existing playlist if is pressed + BAutolock _(fPlaylist); int32 appendIndex = modifiers() & B_SHIFT_KEY ? fPlaylist->CountItems() : -1; msg->AddInt32("append_index", appendIndex); @@ -1367,15 +1390,19 @@ MainWin::_KeyDown(BMessage *msg) case 0x48: // numeric keypad left arrow PostMessage(M_SKIP_PREV); return B_OK; -// TODO: Reenable this and use Undo/Redo stack... -// case 0x34: //delete button -// case 0x3e: //d for delete -// case 0x2b: //t for Trash -// if (modifiers() & B_COMMAND_KEY) { -// PostMessage(M_FILE_DELETE); -// return B_OK; -// } -// break; + + case 0x34: //delete button + case 0x3e: //d for delete + case 0x2b: //t for Trash + if (modifiers() & B_COMMAND_KEY) { + BAutolock _(fPlaylist); + BMessage removeMessage(M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH); + removeMessage.AddInt32("playlist index", + fPlaylist->CurrentRefIndex()); + fPlaylistWindow->PostMessage(&removeMessage); + return B_OK; + } + break; } return B_ERROR; @@ -1541,6 +1568,7 @@ MainWin::_UpdateControlsEnabledStatus() if (fHasAudio) enabledButtons |= VOLUME_ENABLED; + BAutolock _(fPlaylist); bool canSkipPrevious, canSkipNext; fPlaylist->GetSkipInfo(&canSkipPrevious, &canSkipNext); if (canSkipPrevious) diff --git a/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.cpp b/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.cpp new file mode 100644 index 0000000000..ce27e1cbd4 --- /dev/null +++ b/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.cpp @@ -0,0 +1,152 @@ +/* + * 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 new file mode 100644 index 0000000000..442dec3565 --- /dev/null +++ b/src/apps/mediaplayer/playlist/EntryRefPlaylistItem.h @@ -0,0 +1,56 @@ +/* + * 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/Playlist.cpp b/src/apps/mediaplayer/playlist/Playlist.cpp index 22c1cce3ef..5066ca4495 100644 --- a/src/apps/mediaplayer/playlist/Playlist.cpp +++ b/src/apps/mediaplayer/playlist/Playlist.cpp @@ -40,11 +40,6 @@ using std::nothrow; // TODO: using BList for objects is bad, replace it with a template -// TODO: Remove this and use Tracker's Command.h once it is moved into the private headers -namespace BPrivate { - const uint32 kMoveToTrash = 'Ttrs'; -} - Playlist::Listener::Listener() {} Playlist::Listener::~Listener() {} void Playlist::Listener::RefAdded(const entry_ref& ref, int32 index) {} diff --git a/src/apps/mediaplayer/playlist/PlaylistItem.cpp b/src/apps/mediaplayer/playlist/PlaylistItem.cpp new file mode 100644 index 0000000000..0334ca7bda --- /dev/null +++ b/src/apps/mediaplayer/playlist/PlaylistItem.cpp @@ -0,0 +1,63 @@ +/* + * Copyright 2009 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "PlaylistItem.h" + + +PlaylistItem::Listener::Listener() +{ +} + +PlaylistItem::Listener::~Listener() +{ +} + +void PlaylistItem::Listener::ItemChanged(const PlaylistItem* item) +{ +} + + +// #pragma mark - + + +PlaylistItem::PlaylistItem() +{ +} + + +PlaylistItem::~PlaylistItem() +{ +} + + +//! You must hold the Playlist lock. +bool +PlaylistItem::AddListener(Listener* listener) +{ + if (listener && !fListeners.HasItem(listener)) + return fListeners.AddItem(listener); + return false; +} + + +//! You must hold the Playlist lock. +void +PlaylistItem::RemoveListener(Listener* listener) +{ + fListeners.RemoveItem(listener); +} + + +void +PlaylistItem::_NotifyListeners() const +{ + BList listeners(fListeners); + int32 count = listeners.CountItems(); + for (int32 i = 0; i < count; i++) { + Listener* listener = (Listener*)listeners.ItemAtFast(i); + listener->ItemChanged(this); + } +} + diff --git a/src/apps/mediaplayer/playlist/PlaylistItem.h b/src/apps/mediaplayer/playlist/PlaylistItem.h new file mode 100644 index 0000000000..0be9b0040c --- /dev/null +++ b/src/apps/mediaplayer/playlist/PlaylistItem.h @@ -0,0 +1,75 @@ +/* + * Copyright 2009 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef PLAYLIST_ITEM_H +#define PLAYLIST_ITEM_H + +#include +#include + +class BDataIO; +class BMediaFile; +class BMessage; + +class PlaylistItem { +public: + class Listener { + public: + Listener(); + virtual ~Listener(); + + virtual void ItemChanged(const PlaylistItem* item); + }; + +public: + PlaylistItem(); + virtual ~PlaylistItem(); + + // 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; + + // properties + virtual status_t SetName(const BString& name) = 0; + virtual status_t GetName(BString& name) const = 0; + + virtual status_t SetTitle(const BString& title) = 0; + virtual status_t GetTitle(BString& title) const = 0; + + virtual status_t SetAuthor(const BString& author) = 0; + virtual status_t GetAuthor(BString& author) const = 0; + + virtual status_t SetAlbum(const BString& album) = 0; + virtual status_t GetAlbum(BString& album) const = 0; + + virtual status_t SetTrackNumber(int32 trackNumber) = 0; + virtual status_t GetTrackNumber(int32& trackNumber) const = 0; + + virtual status_t SetBitRate(int32 bitRate) = 0; + virtual status_t GetBitRate(int32& bitRate) const = 0; + + virtual status_t GetDuration(bigtime_t& duration) const = 0; + + // methods + virtual status_t MoveIntoTrash() = 0; + virtual status_t RestoreFromTrash() = 0; + + // playback + virtual BMediaFile* CreateMediaFile() const = 0; + + // listener support + bool AddListener(Listener* listener); + void RemoveListener(Listener* listener); + +protected: + void _NotifyListeners() const; + +private: + BList fListeners; +}; + +#endif // PLAYLIST_ITEM_H diff --git a/src/apps/mediaplayer/playlist/PlaylistListView.cpp b/src/apps/mediaplayer/playlist/PlaylistListView.cpp index e08f2fa9c7..5b2857e023 100644 --- a/src/apps/mediaplayer/playlist/PlaylistListView.cpp +++ b/src/apps/mediaplayer/playlist/PlaylistListView.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008, Haiku. All rights reserved. + * Copyright 2007-2009, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -56,10 +56,10 @@ text_offset(const font_height& fh) } -class PlaylistItem : public SimpleItem { +class PlaylistListView::Item : public SimpleItem { public: - PlaylistItem(const entry_ref& ref); - virtual ~PlaylistItem(); + Item(const entry_ref& ref); + virtual ~Item(); void Draw(BView* owner, BRect frame, const font_height& fh, @@ -73,20 +73,20 @@ class PlaylistItem : public SimpleItem { }; -PlaylistItem::PlaylistItem(const entry_ref& ref) +PlaylistListView::Item::Item(const entry_ref& ref) : SimpleItem(ref.name), fRef(ref) { } -PlaylistItem::~PlaylistItem() +PlaylistListView::Item::~Item() { } void -PlaylistItem::Draw(BView* owner, BRect frame, const font_height& fh, +PlaylistListView::Item::Draw(BView* owner, BRect frame, const font_height& fh, bool tintedLine, uint32 mode, bool active, uint32 playbackState) { rgb_color color = (rgb_color){ 255, 255, 255, 255 }; @@ -323,7 +323,7 @@ PlaylistListView::MouseDown(BPoint where) float textOffset = text_offset(fFontHeight); for (int32 i = 0; - PlaylistItem* item = dynamic_cast(ItemAt(i)); i++) { + Item* item = dynamic_cast(ItemAt(i)); i++) { BRect r = ItemFrame(i); if (r.Contains(where)) { if (clicks == 2) { @@ -385,15 +385,14 @@ PlaylistListView::CopyItems(const BList& indices, int32 toIndex) void PlaylistListView::RemoveItemList(const BList& indices) { - fCommandStack->Perform(new (nothrow) RemovePLItemsCommand(fPlaylist, - (int32*)indices.Items(), indices.CountItems())); + RemoveItemList(indices, false); } void PlaylistListView::DrawListItem(BView* owner, int32 index, BRect frame) const { - if (PlaylistItem* item = dynamic_cast(ItemAt(index))) { + if (Item* item = dynamic_cast(ItemAt(index))) { item->Draw(owner, frame, fFontHeight, index % 2, DISPLAY_NAME, index == fCurrentPlaylistIndex, fPlaybackState); } @@ -448,8 +447,24 @@ PlaylistListView::RemoveSelectionToTrash() { BList indices; GetSelectedItems(indices); + RemoveItemList(indices, true); +} + + +void +PlaylistListView::RemoveToTrash(int32 index) +{ + BList indices; + indices.AddItem((void*)index); + RemoveItemList(indices, true); +} + + +void +PlaylistListView::RemoveItemList(const BList& indices, bool intoTrash) +{ fCommandStack->Perform(new (nothrow) RemovePLItemsCommand(fPlaylist, - (int32*)indices.Items(), indices.CountItems(), true)); + (int32*)indices.Items(), indices.CountItems(), intoTrash)); } @@ -496,7 +511,7 @@ PlaylistListView::_FullSync() void PlaylistListView::_AddItem(const entry_ref& ref, int32 index) { - PlaylistItem* item = new (nothrow) PlaylistItem(ref); + Item* item = new (nothrow) Item(ref); if (item) AddItem(item, index); } diff --git a/src/apps/mediaplayer/playlist/PlaylistListView.h b/src/apps/mediaplayer/playlist/PlaylistListView.h index 762af204b7..98a3fd0690 100644 --- a/src/apps/mediaplayer/playlist/PlaylistListView.h +++ b/src/apps/mediaplayer/playlist/PlaylistListView.h @@ -1,5 +1,5 @@ /* - * Copyright 2007, Haiku. All rights reserved. + * Copyright 2007-2009, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -14,11 +14,10 @@ class CommandStack; class Controller; class ControllerObserver; class Playlist; -class PlaylistItem; class PlaylistObserver; class PlaylistListView : public SimpleListView { - public: +public: PlaylistListView(BRect frame, Playlist* playlist, Controller* controller, @@ -46,8 +45,13 @@ class PlaylistListView : public SimpleListView { void Randomize(); void RemoveSelectionToTrash(); + void RemoveToTrash(int32 index); + void RemoveItemList(const BList& indices, + bool intoTrash); + +private: + class Item; - private: void _FullSync(); void _AddItem(const entry_ref& ref, int32 index); void _RemoveItem(int32 index); @@ -67,7 +71,7 @@ class PlaylistListView : public SimpleListView { uint32 fPlaybackState; font_height fFontHeight; - PlaylistItem* fLastClickedItem; + Item* fLastClickedItem; }; #endif // PLAYLIST_LIST_VIEW_H diff --git a/src/apps/mediaplayer/playlist/PlaylistWindow.cpp b/src/apps/mediaplayer/playlist/PlaylistWindow.cpp index 972f0c0982..70549b792b 100644 --- a/src/apps/mediaplayer/playlist/PlaylistWindow.cpp +++ b/src/apps/mediaplayer/playlist/PlaylistWindow.cpp @@ -55,8 +55,7 @@ enum { M_PLAYLIST_EMPTY = 'emty', M_PLAYLIST_RANDOMIZE = 'rand', - M_PLAYLIST_REMOVE = 'rmov', - M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH = 'rmtr' + M_PLAYLIST_REMOVE = 'rmov' }; #define SPACE 5 @@ -198,8 +197,16 @@ PlaylistWindow::MessageReceived(BMessage* message) fListView->RemoveSelected(); break; case M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH: - fListView->RemoveSelectionToTrash(); + { +printf("M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH\n"); +message->PrintToStream(); + int32 index; + if (message->FindInt32("playlist index", &index) == B_OK) + fListView->RemoveToTrash(index); + else + fListView->RemoveSelectionToTrash(); break; + } default: BWindow::MessageReceived(message); break; diff --git a/src/apps/mediaplayer/playlist/PlaylistWindow.h b/src/apps/mediaplayer/playlist/PlaylistWindow.h index fd65b76057..aec21071ce 100644 --- a/src/apps/mediaplayer/playlist/PlaylistWindow.h +++ b/src/apps/mediaplayer/playlist/PlaylistWindow.h @@ -27,6 +27,10 @@ class RWLocker; class BButton; class BFilePanel; +enum { + M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH = 'rmtr' +}; + class PlaylistWindow : public BWindow { public: PlaylistWindow(BRect frame,