First crack at playlist "supplant" functionality. More testing needed

but most of the work is there.
This commit is contained in:
casey langen 2017-07-11 09:42:01 -07:00
parent 0623522f2a
commit 9ed222ab1f
9 changed files with 114 additions and 36 deletions

View File

@ -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

View File

@ -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<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> lock(this->playlistMutex);
this->CopyFrom(source);
this->unshuffled.Clear();
if (source != &playlist) {
this->CopyFrom(source);
this->unshuffled.Clear();
}
}
if (index <= source->Count()) {

View File

@ -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; }

View File

@ -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,

View File

@ -75,6 +75,7 @@ static std::unordered_map<std::string, Id> 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, std::string, EnumHasher> 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" },

View File

@ -83,6 +83,7 @@ namespace musik {
PlayQueuePlaylistSave,
PlayQueuePlaylistRename,
PlayQueuePlaylistDelete,
PlayQueueSupplant,
/* browse ->playlists */
BrowsePlaylistsNew,

View File

@ -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);
}
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -40,6 +40,7 @@
#include <cursespp/Text.h>
#include <core/library/LocalLibraryConstants.h>
#include <core/audio/PlaybackService.h>
#include <glue/util/Duration.h>
@ -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);