Playlist updates are now reflected in the UI, in real time, when changed

from remote devices.
This commit is contained in:
casey langen 2017-12-05 15:10:15 -08:00
parent fc84edf72f
commit ab10608d7a
15 changed files with 176 additions and 74 deletions

View File

@ -229,6 +229,7 @@
<ClInclude Include="sdk\ITagStore.h" />
<ClInclude Include="sdk\IVisualizer.h" />
<ClInclude Include="support\Common.h" />
<ClInclude Include="support\Messages.h" />
<ClInclude Include="support\PreferenceKeys.h" />
<ClInclude Include="support\Preferences.h" />
<ClInclude Include="utfutil.h" />

View File

@ -477,5 +477,8 @@
<ClInclude Include="sdk\IEncoderFactory.h">
<Filter>src\sdk\audio</Filter>
</ClInclude>
<ClInclude Include="support\Messages.h">
<Filter>src\support</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -65,6 +65,7 @@ namespace musik { namespace core {
virtual int Id() = 0;
virtual const std::string& Name() = 0;
virtual void SetMessageQueue(musik::core::runtime::IMessageQueue& queue) = 0;
virtual musik::core::runtime::IMessageQueue& GetMessageQueue() = 0;
virtual void Close() = 0;
};

View File

@ -80,6 +80,7 @@ namespace musik { namespace core { namespace library {
virtual int Id() override;
virtual const std::string& Name() override;
virtual void SetMessageQueue(musik::core::runtime::IMessageQueue& queue) override;
virtual musik::core::runtime::IMessageQueue& GetMessageQueue() override { return *messageQueue; }
virtual void Close() override;
/* IMessageTarget */

View File

@ -49,6 +49,8 @@
#include <core/library/query/local/TrackListQueryBase.h>
#include <core/library/track/LibraryTrack.h>
#include <core/library/LocalLibraryConstants.h>
#include <core/runtime/Message.h>
#include <core/support/Messages.h>
#include <vector>
#include <map>
@ -58,6 +60,7 @@ using namespace musik::core;
using namespace musik::core::db;
using namespace musik::core::db::local;
using namespace musik::core::library;
using namespace musik::core::runtime;
using namespace musik::core::sdk;
/* QUERIES */
@ -226,6 +229,11 @@ class RemoveFromPlaylistQuery : public LocalQueryBase {
this->updated = 0;
}
if (this->updated > 0) {
this->library->GetMessageQueue().Broadcast(
Message::Create(nullptr, message::PlaylistModified, playlistId));
}
return true;
}
@ -427,7 +435,7 @@ static uint64_t savePlaylist(
if (query->GetStatus() == IQuery::Finished) {
if (strlen(playlistName)) {
query = SavePlaylistQuery::Rename(playlistId, playlistName);
query = SavePlaylistQuery::Rename(library, playlistId, playlistName);
library->Enqueue(query, ILibrary::QuerySynchronous);
@ -520,7 +528,7 @@ bool LocalSimpleDataProvider::RenamePlaylist(const int64_t playlistId, const cha
if (strlen(name)) {
try {
std::shared_ptr<SavePlaylistQuery> query =
SavePlaylistQuery::Rename(playlistId, name);
SavePlaylistQuery::Rename(library, playlistId, name);
this->library->Enqueue(query, ILibrary::QuerySynchronous);
@ -539,7 +547,7 @@ bool LocalSimpleDataProvider::RenamePlaylist(const int64_t playlistId, const cha
bool LocalSimpleDataProvider::DeletePlaylist(const int64_t playlistId) {
try {
std::shared_ptr<DeletePlaylistQuery> query =
std::make_shared<DeletePlaylistQuery>(playlistId);
std::make_shared<DeletePlaylistQuery>(library, playlistId);
this->library->Enqueue(query, ILibrary::QuerySynchronous);

View File

@ -37,6 +37,8 @@
#include <core/library/track/LibraryTrack.h>
#include <core/library/query/local/TrackMetadataQuery.h>
#include <core/library/LocalLibraryConstants.h>
#include <core/runtime/Message.h>
#include <core/support/Messages.h>
#include <core/db/Statement.h>
using musik::core::db::Statement;
@ -47,6 +49,7 @@ using namespace musik::core::db;
using namespace musik::core::db::local;
using namespace musik::core::library::constants;
using namespace musik::core::sdk;
using namespace musik::core::runtime;
static std::string INSERT_PLAYLIST_TRACK_QUERY =
"INSERT INTO playlist_tracks (track_external_id, source_id, playlist_id, sort_order) "
@ -145,5 +148,8 @@ bool AppendPlaylistQuery::OnRun(musik::core::db::Connection &db) {
transaction.CommitAndRestart();
this->library->GetMessageQueue().Broadcast(
Message::Create(nullptr, message::PlaylistModified, playlistId));
return true;
}

View File

@ -37,10 +37,13 @@
#include <core/db/ScopedTransaction.h>
#include <core/db/Statement.h>
#include <core/support/Messages.h>
#include <core/runtime/Message.h>
using namespace musik::core;
using namespace musik::core::db;
using namespace musik::core::db::local;
using namespace musik::core::runtime;
static std::string DELETE_PLAYLIST_TRACKS_QUERY =
"DELETE FROM playlist_tracks WHERE playlist_id=?;";
@ -48,7 +51,8 @@ static std::string DELETE_PLAYLIST_TRACKS_QUERY =
static std::string DELETE_PLAYLIST_QUERY =
"DELETE FROM playlists WHERE id=?;";
DeletePlaylistQuery::DeletePlaylistQuery(const int64_t playlistId) {
DeletePlaylistQuery::DeletePlaylistQuery(musik::core::ILibraryPtr library, int64_t playlistId) {
this->library = library;
this->playlistId = playlistId;
}
@ -58,7 +62,7 @@ DeletePlaylistQuery::~DeletePlaylistQuery() {
bool DeletePlaylistQuery::OnRun(musik::core::db::Connection &db) {
ScopedTransaction transaction(db);
/* create playlist */
/* delete the tracks */
Statement deleteTracks(DELETE_PLAYLIST_TRACKS_QUERY.c_str(), db);
deleteTracks.BindInt64(0, this->playlistId);
@ -67,7 +71,7 @@ bool DeletePlaylistQuery::OnRun(musik::core::db::Connection &db) {
return false;
}
/* add tracks to playlist */
/* delete the container */
Statement deletePlaylist(DELETE_PLAYLIST_QUERY.c_str(), db);
deletePlaylist.BindInt64(0, this->playlistId);
@ -76,5 +80,8 @@ bool DeletePlaylistQuery::OnRun(musik::core::db::Connection &db) {
return false;
}
this->library->GetMessageQueue().Broadcast(
Message::Create(nullptr, message::PlaylistDeleted, playlistId));
return true;
}

View File

@ -34,6 +34,7 @@
#pragma once
#include <core/library/ILibrary.h>
#include <core/library/query/local/LocalQueryBase.h>
#include <core/db/Connection.h>
@ -41,7 +42,10 @@ namespace musik { namespace core { namespace db { namespace local {
class DeletePlaylistQuery : public musik::core::db::LocalQueryBase {
public:
DeletePlaylistQuery(const int64_t playlistId);
DeletePlaylistQuery(
musik::core::ILibraryPtr library,
const int64_t playlistId);
virtual ~DeletePlaylistQuery();
virtual std::string Name() { return "DeletePlaylistQuery"; }
@ -51,6 +55,7 @@ namespace musik { namespace core { namespace db { namespace local {
private:
int64_t playlistId;
musik::core::ILibraryPtr library;
};
} } } }

View File

@ -40,10 +40,13 @@
#include <core/library/query/local/TrackMetadataQuery.h>
#include <core/db/ScopedTransaction.h>
#include <core/db/Statement.h>
#include <core/runtime/Message.h>
#include <core/support/Messages.h>
using namespace musik::core;
using namespace musik::core::db;
using namespace musik::core::db::local;
using namespace musik::core::runtime;
/* CONSTANTS */
@ -111,10 +114,12 @@ std::shared_ptr<SavePlaylistQuery> SavePlaylistQuery::Replace(
}
std::shared_ptr<SavePlaylistQuery> SavePlaylistQuery::Rename(
const int64_t playlistId, const std::string& playlistName)
musik::core::ILibraryPtr library,
const int64_t playlistId,
const std::string& playlistName)
{
return std::shared_ptr<SavePlaylistQuery>(
new SavePlaylistQuery(playlistId, playlistName));
new SavePlaylistQuery(library, playlistId, playlistName));
}
std::shared_ptr<SavePlaylistQuery> SavePlaylistQuery::Append(
@ -223,9 +228,11 @@ SavePlaylistQuery::SavePlaylistQuery(
}
SavePlaylistQuery::SavePlaylistQuery(
musik::core::ILibraryPtr library,
const int64_t playlistId,
const std::string& playlistName)
{
this->library = library;
this->categoryId = -1;
this->playlistId = playlistId;
this->playlistName = playlistName;
@ -325,6 +332,9 @@ bool SavePlaylistQuery::CreatePlaylist(musik::core::db::Connection &db) {
}
}
this->library->GetMessageQueue().Broadcast(
Message::Create(nullptr, message::PlaylistCreated, playlistId));
return true;
}
@ -332,7 +342,14 @@ bool SavePlaylistQuery::RenamePlaylist(musik::core::db::Connection &db) {
Statement renamePlaylist(RENAME_PLAYLIST_QUERY.c_str(), db);
renamePlaylist.BindText(0, this->playlistName);
renamePlaylist.BindInt64(1, this->playlistId);
return (renamePlaylist.Step() != db::Error);
bool result = (renamePlaylist.Step() != db::Error);
if (result) {
this->library->GetMessageQueue().Broadcast(
Message::Create(nullptr, message::PlaylistRenamed, playlistId));
}
return result;
}
bool SavePlaylistQuery::ReplacePlaylist(musik::core::db::Connection &db) {
@ -353,6 +370,9 @@ bool SavePlaylistQuery::ReplacePlaylist(musik::core::db::Connection &db) {
return false;
}
this->library->GetMessageQueue().Broadcast(
Message::Create(nullptr, message::PlaylistModified, playlistId));
return true;
}
@ -367,6 +387,9 @@ bool SavePlaylistQuery::AppendToPlaylist(musik::core::db::Connection& db) {
transaction.Cancel();
}
this->library->GetMessageQueue().Broadcast(
Message::Create(nullptr, message::PlaylistModified, playlistId));
return result;
}

View File

@ -71,6 +71,7 @@ namespace musik { namespace core { namespace db { namespace local {
musik::core::sdk::ITrackList* tracks);
static std::shared_ptr<SavePlaylistQuery> Rename(
musik::core::ILibraryPtr library,
const int64_t playlistId,
const std::string& playlistName);
@ -128,6 +129,7 @@ namespace musik { namespace core { namespace db { namespace local {
int64_t categoryId);
SavePlaylistQuery(
musik::core::ILibraryPtr library,
const int64_t playlistId,
const std::string& newName);

View File

@ -0,0 +1,50 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2017 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
namespace musik {
namespace core {
namespace message {
static const int First = 512;
static const int PlaylistModified = First + 1;
static const int PlaylistCreated = First + 2;
static const int PlaylistRenamed = First + 3;
static const int PlaylistDeleted = First + 4;
static const int User = 4096;
}
}
}

View File

@ -39,6 +39,7 @@
#include <core/library/LocalLibraryConstants.h>
#include <core/library/query/local/CategoryTrackListQuery.h>
#include <core/library/query/local/SavePlaylistQuery.h>
#include <core/support/Messages.h>
#include <core/i18n/Locale.h>
#include <app/util/Hotkeys.h>
#include <app/util/Playback.h>
@ -47,6 +48,7 @@
#include "BrowseLayout.h"
using namespace musik;
using namespace musik::core::library::constants;
using namespace musik::core;
using namespace musik::core::audio;
@ -156,22 +158,31 @@ void BrowseLayout::InitializeWindows() {
}
void BrowseLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
if (message.Type() == message::IndexerProgress) {
int64_t id = this->categoryList->GetSelectedId();
auto filter = this->categoryList->GetFilter();
this->categoryList->Requery(filter, id);
}
else if (message.Type() == message::TracksAddedToPlaylist) {
if (this->IsPlaylist() &&
this->categoryList->GetSelectedId() == message.UserData1())
{
this->RequeryTrackList(this->categoryList.get());
switch (message.Type()) {
case cube::message::IndexerProgress: {
int64_t id = this->categoryList->GetSelectedId();
auto filter = this->categoryList->GetFilter();
this->categoryList->Requery(filter, id);
break;
}
}
else if (message.Type() == message::PlaylistCreated) {
if (this->IsPlaylist()) {
auto lastId = this->categoryList->GetSelectedId();
this->categoryList->Requery(this->categoryList->GetFilter(), lastId);
case core::message::PlaylistModified: {
if (this->IsPlaylist() &&
this->categoryList->GetSelectedId() == message.UserData1())
{
this->RequeryTrackList(this->categoryList.get());
}
break;
}
case core::message::PlaylistCreated:
case core::message::PlaylistDeleted:
case core::message::PlaylistRenamed: {
if (this->IsPlaylist()) {
auto lastId = this->categoryList->GetSelectedId();
this->categoryList->Requery(this->categoryList->GetFilter(), lastId);
}
break;
}
}

View File

@ -40,6 +40,7 @@
#include <core/library/LocalLibraryConstants.h>
#include <core/runtime/Message.h>
#include <core/support/Messages.h>
#include <app/overlay/PlayQueueOverlays.h>
#include <app/util/Hotkeys.h>
@ -58,6 +59,7 @@ using namespace musik::core::runtime;
(this->visibleLayout == target) && \
(this->shortcuts && !this->shortcuts->IsFocused())
using namespace musik;
using namespace musik::core;
using namespace musik::core::audio;
using namespace musik::core::library;
@ -300,10 +302,10 @@ void LibraryLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
switch (message.Type()) {
case message::JumpToCategory: {
static std::map<int, const char*> JUMP_TYPE_TO_COLUMN = {
{ message::category::Album, constants::Track::ALBUM },
{ message::category::Artist, constants::Track::ARTIST },
{ message::category::AlbumArtist, constants::Track::ALBUM_ARTIST },
{ message::category::Genre, constants::Track::GENRE }
{ cube::message::category::Album, constants::Track::ALBUM },
{ cube::message::category::Artist, constants::Track::ARTIST },
{ cube::message::category::AlbumArtist, constants::Track::ALBUM_ARTIST },
{ cube::message::category::Genre, constants::Track::GENRE }
};
auto type = JUMP_TYPE_TO_COLUMN[(int)message.UserData1()];
@ -312,8 +314,10 @@ void LibraryLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
}
break;
case message::TracksAddedToPlaylist:
case message::PlaylistCreated: {
case core::message::PlaylistModified:
case core::message::PlaylistCreated:
case core::message::PlaylistRenamed:
case core::message::PlaylistDeleted: {
MessageQueue().Post(Message::Create(
this->browseLayout.get(),
message.Type(),

View File

@ -58,6 +58,7 @@
#define DEFAULT_OVERLAY_WIDTH 30
using namespace musik;
using namespace musik::core;
using namespace musik::core::audio;
using namespace musik::core::db;
@ -207,8 +208,6 @@ static void createNewPlaylist(
if (name.size()) {
auto query = SavePlaylistQuery::Save(library, name, tracks);
library->Enqueue(query, 0, [&queue, callback](auto query) {
queue.Post(Message::Create(nullptr, message::PlaylistCreated));
if (callback) {
callback(query);
}
@ -234,9 +233,7 @@ static void createNewPlaylist(
[&queue, library, categoryType, categoryId](const std::string& name) {
if (name.size()) {
auto query = SavePlaylistQuery::Save(library, name, categoryType, categoryId);
library->Enqueue(query, 0, [&queue](auto query) {
queue.Post(Message::Create(nullptr, message::PlaylistCreated));
});
library->Enqueue(query, 0);
}
});
@ -257,7 +254,7 @@ void PlayQueueOverlays::ShowRenamePlaylistOverlay(
.SetInputAcceptedCallback(
[library, playlistId, callback](const std::string& name) {
if (name.size()) {
library->Enqueue(SavePlaylistQuery::Rename(playlistId, name), 0, callback);
library->Enqueue(SavePlaylistQuery::Rename(library, playlistId, name), 0, callback);
}
});
@ -284,7 +281,7 @@ void PlayQueueOverlays::ShowConfirmDeletePlaylistOverlay(
_TSTR("button_yes"),
[library, playlistId, callback](const std::string& str) {
library->Enqueue(std::shared_ptr<DeletePlaylistQuery>(
new DeletePlaylistQuery(playlistId)), 0, callback);
new DeletePlaylistQuery(library, playlistId)), 0, callback);
});
App::Overlays().Push(dialog);
@ -345,20 +342,20 @@ static void handleJumpTo(
int64_t id;
if (index == 0) {
type = message::category::Album;
type = cube::message::category::Album;
id = track->GetInt64(library::constants::Track::ALBUM_ID);
}
else if (index == 1) {
type = message::category::Artist;
type = cube::message::category::Artist;
id = track->GetInt64(library::constants::Track::ARTIST_ID);
}
else if (index == 2) {
type = message::category::Genre;
type = cube::message::category::Genre;
id = track->GetInt64(library::constants::Track::GENRE_ID);
}
messageQueue.Broadcast(runtime::Message::Create(
nullptr, message::JumpToCategory, type, id));
nullptr, cube::message::JumpToCategory, type, id));
}
static void showAddCategorySelectionToPlaylistOverlay(
@ -399,10 +396,7 @@ static void showAddCategorySelectionToPlaylistOverlay(
auto query = SavePlaylistQuery::Append(
library, playlistId, categoryType, categoryId);
library->Enqueue(query, 0, [&queue, playlistId](auto query) {
/* the nesting is real... */
queue.Post(Message::Create(nullptr, message::TracksAddedToPlaylist, playlistId));
});
library->Enqueue(query, 0);
}
}
},
@ -443,12 +437,7 @@ static void showAddTrackToPlaylistOverlay(
else { /* add to existing */
int64_t playlistId = (*result)[index - 1]->id;
setLastPlaylistId(playlistId);
library->Enqueue(SavePlaylistQuery::Append(library, playlistId, list), 0,
[&queue, playlistId](auto query) {
/* the nesting is real... */
queue.Post(Message::Create(nullptr, message::TracksAddedToPlaylist, playlistId));
});
library->Enqueue(SavePlaylistQuery::Append(library, playlistId, list), 0);
}
}
},

View File

@ -35,14 +35,12 @@
#pragma once
#include "stdafx.h"
#include <core/audio/PlaybackService.h>
#include <app/window/TrackListView.h>
#include <core/support/Messages.h>
namespace musik {
namespace cube {
namespace message {
static const int JumpToCategory = 1024;
static const int First = musik::core::message::User + 1024;
namespace category { /* User1 */
static const int Album = 0;
@ -51,24 +49,17 @@ namespace musik {
static const int Genre = 3;
}
static const int IndexerStarted = 1025;
static const int IndexerProgress = 1026;
static const int IndexerFinished = 1027;
static const int RequeryTrackList = 1028;
static const int RefreshTransport = 1029;
static const int RefreshLogs = 1030;
static const int TracksAddedToPlaylist = 1031;
static const int PlaylistCreated = 1032;
static const int UpdateCheckFinished = 1033;
static const int JumpToConsole = 1034;
static const int JumpToLibrary = 1035;
static const int JumpToSettings = 1036;
static const int JumpToCategory = First + 1;
static const int IndexerStarted = First + 2;
static const int IndexerProgress = First + 3;
static const int IndexerFinished = First + 4;
static const int RequeryTrackList = First + 5;
static const int RefreshTransport = First + 6;
static const int RefreshLogs = First + 7;
static const int UpdateCheckFinished = First + 8;
static const int JumpToConsole = First + 9;
static const int JumpToLibrary = First + 10;
static const int JumpToSettings = First + 11;
}
}
}