diff --git a/musikcube.sln b/musikcube.sln index e7bc2dac9..e57a09a0e 100644 --- a/musikcube.sln +++ b/musikcube.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26403.0 +VisualStudioVersion = 15.0.26430.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "musikbox", "src\musikbox\musikbox.vcxproj", "{C7102EB1-7311-4B36-A7FF-89DD7F077FF9}" ProjectSection(ProjectDependencies) = postProject @@ -71,6 +71,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "websocket_remote", "src\plu EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpdatastream", "src\plugins\httpdatastream\httpdatastream.vcxproj", "{FA74D37C-8184-4596-BFE9-766C159045E1}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{CE0E0AF3-A106-4992-BEBD-B842B983D0FE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -201,4 +203,20 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {292974B0-C8B7-41EF-B603-554A2B25CB90} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {54764854-5A73-4329-9BAD-9AF22C72D9E2} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {7CD00EC4-D090-48BE-9388-FA4857AC332C} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {4F10C17A-8AF7-4FAC-A4E2-087AE6E8F9D8} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {465EF178-91C1-4068-BE1D-F9616ECCB6DE} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {4993E68D-E97A-4CD2-AC8E-168AE315BAC5} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {3E30064E-B9C4-4690-8AC2-2C694176A319} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {68AA481E-3CCE-440F-8CCE-69F1B371C89D} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {CA56A398-7F9A-493A-A7FC-C6B4D550B674} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {51C18730-DC48-411A-829D-F2B3B7AC4C97} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {BA3902E0-8915-4E59-AD3B-F9960507F234} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {43A78C57-C9A3-4852-B0BE-05335C5C077D} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + {FA74D37C-8184-4596-BFE9-766C159045E1} = {CE0E0AF3-A106-4992-BEBD-B842B983D0FE} + EndGlobalSection EndGlobal diff --git a/src/core/audio/PlaybackService.cpp b/src/core/audio/PlaybackService.cpp index 45a81dbd1..e212bb93a 100755 --- a/src/core/audio/PlaybackService.cpp +++ b/src/core/audio/PlaybackService.cpp @@ -466,15 +466,49 @@ PlaybackState PlaybackService::GetPlaybackState() { return transport.GetPlaybackState(); } -void PlaybackService::Play(const TrackList& tracks, size_t index) { - /* do the copy outside of the critical section, then swap. */ - TrackList temp(this->library); - temp.CopyFrom(tracks); +bool PlaybackService::Supplant(const TrackList& tracks, size_t index) { + if (&tracks == &playlist) { + return true; + } + auto playingTrack = this->GetPlaying(); + if (playingTrack && tracks.Count() > index) { + auto supplantTrack = tracks.Get(index); + auto supplantLibrary = supplantTrack->Library(); + auto supplantId = tracks.GetId(index); + + auto playingId = playingTrack->GetId(); + auto playingLibrary = playingTrack->Library(); + + if (supplantId == playingId && supplantLibrary == playingLibrary) { + { + std::unique_lock lock(this->playlistMutex); + TrackList temp(this->library); + temp.CopyFrom(tracks); + this->playlist.Swap(temp); + this->unshuffled.Clear(); + this->index = index; + this->nextIndex = NO_POSITION; + } + + POST(this, MESSAGE_PREPARE_NEXT_TRACK, this->index, 0); + POST(this, MESSAGE_NOTIFY_EDITED, NO_POSITION, 0); + } + } + + return false; +} + +void PlaybackService::Play(const TrackList& tracks, size_t index) { { std::unique_lock lock(this->playlistMutex); - this->playlist.Swap(temp); - this->unshuffled.Clear(); + + if (&tracks != &playlist) { + TrackList temp(this->library); + temp.CopyFrom(tracks); + this->playlist.Swap(temp); + this->unshuffled.Clear(); + } } if (index <= tracks.Count()) { @@ -497,8 +531,10 @@ void PlaybackService::Play(const musik::core::sdk::ITrackList* source, size_t in /* otherwise use slower impl to be compatible with SDK */ { std::unique_lock lock(this->playlistMutex); - this->CopyFrom(source); - this->unshuffled.Clear(); + if (source != &playlist) { + this->CopyFrom(source); + this->unshuffled.Clear(); + } } if (index <= source->Count()) { diff --git a/src/core/audio/PlaybackService.h b/src/core/audio/PlaybackService.h index f2f052578..3f60cbde5 100755 --- a/src/core/audio/PlaybackService.h +++ b/src/core/audio/PlaybackService.h @@ -106,6 +106,9 @@ namespace musik { namespace core { namespace audio { virtual musik::core::sdk::TimeChangeMode GetTimeChangeMode(); virtual void SetTimeChangeMode(musik::core::sdk::TimeChangeMode); + /* TODO: include in SDK? */ + virtual bool Supplant(const TrackList& source, size_t index); + /* app-specific implementation. similar to some SDK methods, but use concrete data types with known optimizations */ musik::core::audio::ITransport& GetTransport() { return this->transport; } diff --git a/src/musikbox/app/layout/NowPlayingLayout.cpp b/src/musikbox/app/layout/NowPlayingLayout.cpp index 2c1ee0a70..2e6d37581 100755 --- a/src/musikbox/app/layout/NowPlayingLayout.cpp +++ b/src/musikbox/app/layout/NowPlayingLayout.cpp @@ -218,14 +218,7 @@ void NowPlayingLayout::OnPlaylistSelected(int64_t playlistId) { } bool NowPlayingLayout::KeyPress(const std::string& key) { - if (key == "KEY_ENTER") { - size_t index = this->trackListView->GetSelectedIndex(); - if (index != ListWindow::NO_SELECTION) { - this->playback.Play(index); - return true; - } - } - else if (Hotkeys::Is(Hotkeys::PlayQueuePlaylistLoad, key)) { + if (Hotkeys::Is(Hotkeys::PlayQueuePlaylistLoad, key)) { PlayQueueOverlays::ShowLoadPlaylistOverlay( this->playback, this->library, diff --git a/src/musikbox/app/util/Hotkeys.cpp b/src/musikbox/app/util/Hotkeys.cpp index c89ac0b7e..61a31503a 100755 --- a/src/musikbox/app/util/Hotkeys.cpp +++ b/src/musikbox/app/util/Hotkeys.cpp @@ -75,6 +75,7 @@ static std::unordered_map NAME_TO_ID = { { "play_queue_playlist_save", Id::PlayQueuePlaylistSave }, { "play_queue_playlist_rename", Id::PlayQueuePlaylistRename }, { "play_queue_playlist_delete", Id::PlayQueuePlaylistDelete }, + { "play_queue_supplant", Id::PlayQueueSupplant }, { "browse_playlists_new", Id::BrowsePlaylistsNew }, { "browse_playlists_save", Id::BrowsePlaylistsSave }, @@ -133,6 +134,7 @@ static std::unordered_map ID_TO_DEFAULT = { { Id::PlayQueuePlaylistSave, "M-s" }, { Id::PlayQueuePlaylistRename, "M-r" }, { Id::PlayQueuePlaylistDelete, "M-x" }, + { Id::PlayQueueSupplant, "M-a" }, { Id::BrowsePlaylistsSave, "M-s" }, { Id::BrowsePlaylistsNew, "M-n" }, diff --git a/src/musikbox/app/util/Hotkeys.h b/src/musikbox/app/util/Hotkeys.h index 50a7ab84d..b72a818f6 100755 --- a/src/musikbox/app/util/Hotkeys.h +++ b/src/musikbox/app/util/Hotkeys.h @@ -83,6 +83,7 @@ namespace musik { PlayQueuePlaylistSave, PlayQueuePlaylistRename, PlayQueuePlaylistDelete, + PlayQueueSupplant, /* browse ->playlists */ BrowsePlaylistsNew, diff --git a/src/musikbox/app/util/Playback.cpp b/src/musikbox/app/util/Playback.cpp index 4bea6726f..0b0be0eaf 100755 --- a/src/musikbox/app/util/Playback.cpp +++ b/src/musikbox/app/util/Playback.cpp @@ -38,29 +38,44 @@ using namespace musik::core::audio; using namespace musik::core::sdk; +using namespace musik::box; + +static const size_t NO_SELECTION = (size_t) -1; + +static size_t getSelectedIndex(TrackListView& trackList) { + auto tracks = trackList.GetTrackList(); + size_t index = 0; + + if (tracks && tracks->Count()) { + if (trackList.IsFocused()) { + index = trackList.GetSelectedTrackIndex(); + if (index == cursespp::ListWindow::NO_SELECTION) { + return NO_SELECTION; + } + } + } + + return index; +} namespace musik { namespace box { namespace playback { - void Play( - musik::box::TrackListView& trackList, - musik::core::audio::PlaybackService& playback) - { - auto tracks = trackList.GetTrackList(); - - if (tracks && tracks->Count()) { - size_t index = 0; - - if (trackList.IsFocused()) { - index = trackList.GetSelectedTrackIndex(); - if (index == cursespp::ListWindow::NO_SELECTION) { - return; - } - } - + void Play(TrackListView& trackList, PlaybackService& playback) { + auto index = getSelectedIndex(trackList); + if (index != NO_SELECTION) { + auto tracks = trackList.GetTrackList(); playback.Play(*tracks, index); } } + + void Supplant(TrackListView& trackList, PlaybackService& playback) { + auto index = getSelectedIndex(trackList); + if (index != NO_SELECTION) { + auto tracks = trackList.GetTrackList(); + playback.Supplant(*tracks, index); + } + } } } } diff --git a/src/musikbox/app/util/Playback.h b/src/musikbox/app/util/Playback.h index 56a3ace36..39206f1f6 100755 --- a/src/musikbox/app/util/Playback.h +++ b/src/musikbox/app/util/Playback.h @@ -45,6 +45,10 @@ namespace musik { void Play( musik::box::TrackListView& trackList, musik::core::audio::PlaybackService& playback); + + void Supplant( + musik::box::TrackListView& trackList, + musik::core::audio::PlaybackService& playback); } } } diff --git a/src/musikbox/app/window/TrackListView.cpp b/src/musikbox/app/window/TrackListView.cpp index 345fdcd48..dde8bc81d 100755 --- a/src/musikbox/app/window/TrackListView.cpp +++ b/src/musikbox/app/window/TrackListView.cpp @@ -40,6 +40,7 @@ #include #include +#include #include @@ -212,13 +213,12 @@ bool TrackListView::KeyPress(const std::string& key) { PlayQueueOverlays::ShowAlbumDividerOverlay( MessageQueue(), this->playback, this->library, track); - - handled = true; } else { playback::Play(*this, this->playback); - handled = true; } + + handled = true; } else if (Hotkeys::Is(Hotkeys::ContextMenu, key)) { if (!headers.HeaderAt(this->GetSelectedIndex())) { @@ -234,6 +234,12 @@ bool TrackListView::KeyPress(const std::string& key) { this->ScrollToPlaying(); handled = true; } + else if (Hotkeys::Is(Hotkeys::PlayQueueSupplant, key)) { + if (!headers.HeaderAt(this->GetSelectedIndex())) { + playback::Supplant(*this, this->playback); + } + handled = true; + } if (!handled) { handled = ListWindow::KeyPress(key);