Some initial plumbing to test query serialization/deserialization so we

can make requests over websockets.
This commit is contained in:
casey langen 2020-09-30 23:08:03 -07:00
parent b181ed50f6
commit 4ee0b92323
34 changed files with 595 additions and 61 deletions

View File

@ -59,7 +59,7 @@
#include <core/sdk/IStreamingEncoder.h> #include <core/sdk/IStreamingEncoder.h>
#include <core/sdk/IDevice.h> #include <core/sdk/IDevice.h>
#include <core/sdk/IOutput.h> #include <core/sdk/IOutput.h>
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/library/ILibrary.h> #include <core/library/ILibrary.h>
#include <core/library/IIndexer.h> #include <core/library/IIndexer.h>
#include <core/library/track/TrackList.h> #include <core/library/track/TrackList.h>
@ -1266,7 +1266,7 @@ mcsdk_export void mcsdk_svc_indexer_remove_callbacks(mcsdk_svc_indexer in, mcsdk
* ILibrary * ILibrary
*/ */
class mcsdk_db_wrapped_query: public LocalQueryBase { class mcsdk_db_wrapped_query: public QueryBase {
public: public:
mcsdk_db_wrapped_query( mcsdk_db_wrapped_query(
mcsdk_svc_library library, mcsdk_svc_library library,

View File

@ -500,6 +500,7 @@
<ClCompile Include="library\LocalMetadataProxy.cpp" /> <ClCompile Include="library\LocalMetadataProxy.cpp" />
<ClCompile Include="library\metadata\MetadataMap.cpp" /> <ClCompile Include="library\metadata\MetadataMap.cpp" />
<ClCompile Include="library\metadata\MetadataMapList.cpp" /> <ClCompile Include="library\metadata\MetadataMapList.cpp" />
<ClCompile Include="library\QueryRegistry.cpp" />
<ClCompile Include="library\query\local\AlbumListQuery.cpp" /> <ClCompile Include="library\query\local\AlbumListQuery.cpp" />
<ClCompile Include="library\query\local\AllCategoriesQuery.cpp" /> <ClCompile Include="library\query\local\AllCategoriesQuery.cpp" />
<ClCompile Include="library\query\local\AppendPlaylistQuery.cpp" /> <ClCompile Include="library\query\local\AppendPlaylistQuery.cpp" />
@ -517,6 +518,7 @@
<ClCompile Include="library\query\local\SetTrackRatingQuery.cpp" /> <ClCompile Include="library\query\local\SetTrackRatingQuery.cpp" />
<ClCompile Include="library\query\local\TrackMetadataQuery.cpp" /> <ClCompile Include="library\query\local\TrackMetadataQuery.cpp" />
<ClCompile Include="library\query\local\util\CategoryQueryUtil.cpp" /> <ClCompile Include="library\query\local\util\CategoryQueryUtil.cpp" />
<ClCompile Include="library\RemoteLibrary.cpp" />
<ClCompile Include="library\track\IndexerTrack.cpp" /> <ClCompile Include="library\track\IndexerTrack.cpp" />
<ClCompile Include="library\track\LibraryTrack.cpp" /> <ClCompile Include="library\track\LibraryTrack.cpp" />
<ClCompile Include="library\track\Track.cpp" /> <ClCompile Include="library\track\Track.cpp" />
@ -577,8 +579,11 @@
<ClInclude Include="library\LibraryFactory.h" /> <ClInclude Include="library\LibraryFactory.h" />
<ClInclude Include="library\LocalLibraryConstants.h" /> <ClInclude Include="library\LocalLibraryConstants.h" />
<ClInclude Include="library\LocalMetadataProxy.h" /> <ClInclude Include="library\LocalMetadataProxy.h" />
<ClInclude Include="library\LocalQueryBase.h" />
<ClInclude Include="library\metadata\MetadataMap.h" /> <ClInclude Include="library\metadata\MetadataMap.h" />
<ClInclude Include="library\metadata\MetadataMapList.h" /> <ClInclude Include="library\metadata\MetadataMapList.h" />
<ClInclude Include="library\QueryBase.h" />
<ClInclude Include="library\QueryRegistry.h" />
<ClInclude Include="library\query\local\AlbumListQuery.h" /> <ClInclude Include="library\query\local\AlbumListQuery.h" />
<ClInclude Include="library\query\local\AllCategoriesQuery.h" /> <ClInclude Include="library\query\local\AllCategoriesQuery.h" />
<ClInclude Include="library\query\local\AppendPlaylistQuery.h" /> <ClInclude Include="library\query\local\AppendPlaylistQuery.h" />
@ -595,11 +600,11 @@
<ClInclude Include="library\query\local\SearchTrackListQuery.h" /> <ClInclude Include="library\query\local\SearchTrackListQuery.h" />
<ClInclude Include="library\query\local\SetTrackRatingQuery.h" /> <ClInclude Include="library\query\local\SetTrackRatingQuery.h" />
<ClInclude Include="library\query\local\TrackListQueryBase.h" /> <ClInclude Include="library\query\local\TrackListQueryBase.h" />
<ClInclude Include="Library\query\local\LocalQueryBase.h" />
<ClInclude Include="library\query\local\TrackMetadataQuery.h" /> <ClInclude Include="library\query\local\TrackMetadataQuery.h" />
<ClInclude Include="library\query\local\util\CategoryQueryUtil.h" /> <ClInclude Include="library\query\local\util\CategoryQueryUtil.h" />
<ClInclude Include="library\query\local\util\SdkWrappers.h" /> <ClInclude Include="library\query\local\util\SdkWrappers.h" />
<ClInclude Include="library\query\local\util\TrackSort.h" /> <ClInclude Include="library\query\local\util\TrackSort.h" />
<ClInclude Include="library\RemoteLibrary.h" />
<ClInclude Include="library\track\IndexerTrack.h" /> <ClInclude Include="library\track\IndexerTrack.h" />
<ClInclude Include="library\track\LibraryTrack.h" /> <ClInclude Include="library\track\LibraryTrack.h" />
<ClInclude Include="library\track\Track.h" /> <ClInclude Include="library\track\Track.h" />

View File

@ -241,6 +241,12 @@
<ClCompile Include="c_interface_wrappers.cpp"> <ClCompile Include="c_interface_wrappers.cpp">
<Filter>src</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="library\RemoteLibrary.cpp">
<Filter>src\library</Filter>
</ClCompile>
<ClCompile Include="library\QueryRegistry.cpp">
<Filter>src\library</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="pch.hpp"> <ClInclude Include="pch.hpp">
@ -399,9 +405,6 @@
<ClInclude Include="library\query\local\CategoryListQuery.h"> <ClInclude Include="library\query\local\CategoryListQuery.h">
<Filter>src\library\query\local</Filter> <Filter>src\library\query\local</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Library\query\local\LocalQueryBase.h">
<Filter>src\library\query\local</Filter>
</ClInclude>
<ClInclude Include="plugin\Plugins.h"> <ClInclude Include="plugin\Plugins.h">
<Filter>src\plugin</Filter> <Filter>src\plugin</Filter>
</ClInclude> </ClInclude>
@ -594,5 +597,17 @@
<ClInclude Include="sdk\ReplayGain.h"> <ClInclude Include="sdk\ReplayGain.h">
<Filter>src\sdk\metadata</Filter> <Filter>src\sdk\metadata</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="library\RemoteLibrary.h">
<Filter>src\library</Filter>
</ClInclude>
<ClInclude Include="library\QueryRegistry.h">
<Filter>src\library</Filter>
</ClInclude>
<ClInclude Include="library\LocalQueryBase.h">
<Filter>src\library</Filter>
</ClInclude>
<ClInclude Include="library\QueryBase.h">
<Filter>src\library</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -54,11 +54,18 @@ namespace musik { namespace core { namespace db {
} Status; } Status;
virtual ~IQuery() { } virtual ~IQuery() { }
virtual int GetStatus() = 0; virtual int GetStatus() = 0;
virtual int GetId() = 0; virtual int GetId() = 0;
virtual int GetOptions() = 0; virtual int GetOptions() = 0;
virtual std::string Name() = 0; virtual std::string Name() = 0;
}; };
class ISerializableQuery: public IQuery {
public:
virtual ~ISerializableQuery() { }
virtual std::string SerializeQuery() = 0;
virtual std::string SerializeResult() = 0;
virtual void DeserializeResult(const std::string& data) = 0;
};
} } } } } }

View File

@ -35,6 +35,7 @@
#include "pch.hpp" #include "pch.hpp"
#include <core/library/LibraryFactory.h> #include <core/library/LibraryFactory.h>
#include <core/library/LocalLibrary.h> #include <core/library/LocalLibrary.h>
#include <core/library/RemoteLibrary.h>
#include <core/db/Connection.h> #include <core/db/Connection.h>
#include <core/support/Common.h> #include <core/support/Common.h>
#include <core/support/Preferences.h> #include <core/support/Preferences.h>
@ -56,20 +57,21 @@ LibraryFactory::LibraryFactory() {
for (size_t i = 0; i < libraries.size(); i++) { for (size_t i = 0; i < libraries.size(); i++) {
std::string name = libraries.at(i); std::string name = libraries.at(i);
int id = prefs->GetInt(name); int id = prefs->GetInt(name);
this->AddLibrary(id, LocalLibrary, name); this->AddLibrary(id, LibraryType::Local, name);
} }
if (this->libraries.empty()) { if (this->libraries.empty()) {
this->CreateLibrary("Local Library", LocalLibrary); this->CreateLibrary("Local Library", LibraryType::Local);
} }
} }
LibraryFactory::~LibraryFactory() { LibraryFactory::~LibraryFactory() {
} }
ILibraryPtr LibraryFactory::AddLibrary(int id, int type, const std::string& name) ILibraryPtr LibraryFactory::AddLibrary(int id, LibraryType type, const std::string& name) {
{ ILibraryPtr library = (type == LibraryType::Local)
ILibraryPtr library = library::LocalLibrary::Create(name, id); ? library::LocalLibrary::Create(name, id)
: library::RemoteLibrary::Create(name, id);
if (library) { if (library) {
this->libraries.push_back(library); this->libraries.push_back(library);
@ -88,7 +90,7 @@ void LibraryFactory::Shutdown() {
Instance().libraries.clear(); Instance().libraries.clear();
} }
ILibraryPtr LibraryFactory::CreateLibrary(const std::string& name, int type) { ILibraryPtr LibraryFactory::CreateLibrary(const std::string& name, LibraryType type) {
auto prefs = Preferences::ForComponent(prefs::components::Libraries); auto prefs = Preferences::ForComponent(prefs::components::Libraries);
std::vector<std::string> libraries; std::vector<std::string> libraries;
prefs->GetKeys(libraries); prefs->GetKeys(libraries);
@ -113,7 +115,7 @@ ILibraryPtr LibraryFactory::CreateLibrary(const std::string& name, int type) {
++nextId; /* unique */ ++nextId; /* unique */
prefs->SetInt(name, nextId); prefs->SetInt(name, nextId);
return this->AddLibrary(nextId, LocalLibrary, name); return this->AddLibrary(nextId, type, name);
} }
LibraryFactory::LibraryVector& LibraryFactory::Libraries() { LibraryFactory::LibraryVector& LibraryFactory::Libraries() {

View File

@ -48,8 +48,9 @@ namespace musik { namespace core {
typedef std::map<int, ILibraryPtr> LibraryMap; typedef std::map<int, ILibraryPtr> LibraryMap;
typedef sigslot::signal0<> LibrariesUpdatedEvent; typedef sigslot::signal0<> LibrariesUpdatedEvent;
enum LibraryType { enum class LibraryType: int {
LocalLibrary = 1 Local = 1,
Remote = 2
}; };
~LibraryFactory(); ~LibraryFactory();
@ -58,7 +59,7 @@ namespace musik { namespace core {
static LibraryVector& Libraries(); static LibraryVector& Libraries();
static ILibraryPtr Default(); static ILibraryPtr Default();
ILibraryPtr CreateLibrary(const std::string& name, int type); ILibraryPtr CreateLibrary(const std::string& name, LibraryType type);
void Shutdown(); void Shutdown();
ILibraryPtr GetLibrary(int identifier); ILibraryPtr GetLibrary(int identifier);
@ -67,7 +68,7 @@ namespace musik { namespace core {
private: private:
LibraryFactory(); LibraryFactory();
ILibraryPtr AddLibrary(int id, int type, const std::string& name); ILibraryPtr AddLibrary(int id, LibraryType type, const std::string& name);
LibraryVector libraries; LibraryVector libraries;
LibraryMap libraryMap; LibraryMap libraryMap;

View File

@ -36,7 +36,7 @@
#include <core/library/LocalLibrary.h> #include <core/library/LocalLibrary.h>
#include <core/config.h> #include <core/config.h>
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/support/Common.h> #include <core/support/Common.h>
#include <core/support/Preferences.h> #include <core/support/Preferences.h>
#include <core/library/Indexer.h> #include <core/library/Indexer.h>

View File

@ -40,7 +40,7 @@
#include <core/library/ILibrary.h> #include <core/library/ILibrary.h>
#include <core/library/IIndexer.h> #include <core/library/IIndexer.h>
#include <core/library/IQuery.h> #include <core/library/IQuery.h>
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
@ -57,7 +57,7 @@ namespace musik { namespace core { namespace library {
public std::enable_shared_from_this<LocalLibrary> public std::enable_shared_from_this<LocalLibrary>
{ {
public: public:
using LocalQuery = musik::core::db::LocalQueryBase; using LocalQuery = musik::core::db::QueryBase;
using LocalQueryPtr = std::shared_ptr<LocalQuery>; using LocalQueryPtr = std::shared_ptr<LocalQuery>;
static ILibraryPtr Create(std::string name, int id); static ILibraryPtr Create(std::string name, int id);

View File

@ -173,7 +173,7 @@ class ExternalIdListToTrackListQuery : public TrackListQueryBase {
std::shared_ptr<TrackList> result; std::shared_ptr<TrackList> result;
}; };
class RemoveFromPlaylistQuery : public LocalQueryBase { class RemoveFromPlaylistQuery : public QueryBase {
public: public:
RemoveFromPlaylistQuery( RemoveFromPlaylistQuery(
ILibraryPtr library, ILibraryPtr library,

View File

@ -45,16 +45,16 @@
namespace musik { namespace core { namespace db { namespace musik { namespace core { namespace db {
class LocalQueryBase : public IQuery, public sigslot::has_slots<> { class QueryBase: public ISerializableQuery, public sigslot::has_slots<> {
public: public:
LocalQueryBase() QueryBase()
: status(0) : status(0)
, options(0) , options(0)
, queryId(nextId()) , queryId(nextId())
, cancel(false) { , cancel(false) {
} }
virtual ~LocalQueryBase() { virtual ~QueryBase() {
} }
bool Run(musik::core::db::Connection &db) { bool Run(musik::core::db::Connection &db) {
@ -76,6 +76,8 @@ namespace musik { namespace core { namespace db {
return false; return false;
} }
/* IQuery */
virtual int GetStatus() { virtual int GetStatus() {
std::unique_lock<std::mutex> lock(this->stateMutex); std::unique_lock<std::mutex> lock(this->stateMutex);
return this->status; return this->status;
@ -100,6 +102,20 @@ namespace musik { namespace core { namespace db {
virtual std::string Name() = 0; virtual std::string Name() = 0;
/* ISerializableQuery */
virtual std::string SerializeQuery() {
throw std::runtime_error("not implemented");
}
virtual std::string SerializeResult() {
throw std::runtime_error("not implemented");
}
virtual void DeserializeResult(const std::string& data) {
throw std::runtime_error("not implemented");
}
protected: protected:
void SetStatus(int status) { void SetStatus(int status) {
std::unique_lock<std::mutex> lock(this->stateMutex); std::unique_lock<std::mutex> lock(this->stateMutex);

View File

@ -0,0 +1,57 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2019 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.
//
//////////////////////////////////////////////////////////////////////////////
#include "pch.hpp"
#include "QueryRegistry.h"
#include <core/library/query/local/LyricsQuery.h>
using namespace musik::core::db;
using namespace musik::core::db::local;
namespace musik { namespace core { namespace library {
namespace QueryRegistry {
std::shared_ptr<ISerializableQuery> CreateLocalQueryFor(
const std::string& name, const std::string& data)
{
if (name == LyricsQuery::kQueryName) {
return LyricsQuery::DeserializeQuery(data);
}
return std::shared_ptr<ISerializableQuery>();
}
}
} } }

View File

@ -0,0 +1,48 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2019 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
#include <core/library/IQuery.h>
#include <string>
#include <memory>
namespace musik { namespace core { namespace library {
namespace QueryRegistry {
std::shared_ptr<musik::core::db::ISerializableQuery> CreateLocalQueryFor(
const std::string& name, const std::string& data);
}
} } }

View File

@ -0,0 +1,233 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2019 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.
//
//////////////////////////////////////////////////////////////////////////////
#include "pch.hpp"
#include <core/library/RemoteLibrary.h>
#include <core/config.h>
#include <core/support/Common.h>
#include <core/support/Preferences.h>
#include <core/library/Indexer.h>
#include <core/library/IQuery.h>
#include <core/library/QueryRegistry.h>
#include <core/runtime/Message.h>
#include <core/debug.h>
#include <core/library/LibraryFactory.h> /* CAL TODO: remove this */
static const std::string TAG = "RemoteLibrary";
using namespace musik::core;
using namespace musik::core::db;
using namespace musik::core::library;
using namespace musik::core::runtime;
#define MESSAGE_QUERY_COMPLETED 5000
class RemoteLibrary::QueryCompletedMessage: public Message {
public:
using QueryContextPtr = RemoteLibrary::QueryContextPtr;
QueryCompletedMessage(IMessageTarget* target, QueryContextPtr context)
: Message(target, MESSAGE_QUERY_COMPLETED, 0, 0) {
this->context = context;
}
virtual ~QueryCompletedMessage() {
}
QueryContextPtr GetContext() { return this->context; }
private:
QueryContextPtr context;
};
ILibraryPtr RemoteLibrary::Create(std::string name, int id) {
ILibraryPtr lib(new RemoteLibrary(name, id));
return lib;
}
RemoteLibrary::RemoteLibrary(std::string name,int id)
: name(name)
, id(id)
, exit(false)
, messageQueue(nullptr) {
this->identifier = std::to_string(id);
this->thread = new std::thread(std::bind(&RemoteLibrary::ThreadProc, this));
}
RemoteLibrary::~RemoteLibrary() {
this->Close();
}
int RemoteLibrary::Id() {
return this->id;
}
const std::string& RemoteLibrary::Name() {
return this->name;
}
void RemoteLibrary::Close() {
std::thread* thread = nullptr;
{
std::unique_lock<std::recursive_mutex> lock(this->mutex);
if (this->thread) {
thread = this->thread;
this->thread = nullptr;
this->queryQueue.clear();
this->exit = true;
}
}
if (thread) {
this->queueCondition.notify_all();
thread->join();
delete thread;
}
}
int RemoteLibrary::Enqueue(QueryPtr query, unsigned int options, Callback callback) {
auto serializableQuery = std::dynamic_pointer_cast<ISerializableQuery>(query);
if (serializableQuery) {
std::unique_lock<std::recursive_mutex> lock(this->mutex);
if (this->exit) { /* closed */
return -1;
}
auto context = std::make_shared<QueryContext>();
context->query = serializableQuery;
context->callback = callback;
if (options & ILibrary::QuerySynchronous) {
this->RunQuery(context, false); /* false = do not notify via QueryCompleted */
}
else {
queryQueue.push_back(context);
queueCondition.notify_all();
}
return query->GetId();
}
return -1;
}
RemoteLibrary::QueryContextPtr RemoteLibrary::GetNextQuery() {
std::unique_lock<std::recursive_mutex> lock(this->mutex);
while (!this->queryQueue.size() && !this->exit) {
this->queueCondition.wait(lock);
}
if (this->exit) {
return QueryContextPtr();
}
else {
auto front = queryQueue.front();
queryQueue.pop_front();
return front;
}
}
void RemoteLibrary::ThreadProc() {
while (!this->exit) {
auto query = GetNextQuery();
if (query) {
this->RunQuery(query);
}
}
}
void RemoteLibrary::RunQuery(QueryContextPtr context, bool notify) {
if (context) {
auto queryBytes = context->query->SerializeQuery();
auto localQuery = QueryRegistry::CreateLocalQueryFor(context->query->Name(), queryBytes);
auto onComplete = [this, notify, context, localQuery]() {
if (notify) {
if (this->messageQueue) {
this->messageQueue->Post(std::make_shared<QueryCompletedMessage>(this, context));
}
else {
this->QueryCompleted(localQuery.get());
}
}
else if (context->callback) {
context->callback(context->query);
}
context->query.reset();
};
if (!localQuery) {
onComplete();
return;
}
/* CAL TODO: eventually make the request over a websocket. right now we just
do everything via loopback to the local library for testing. */
LibraryFactory::Default()->Enqueue(
localQuery,
0,
[context, onComplete, localQuery](auto result) {
if (localQuery->GetStatus() == IQuery::Finished) {
context->query->DeserializeResult(localQuery->SerializeResult());
}
onComplete();
});
}
}
void RemoteLibrary::SetMessageQueue(musik::core::runtime::IMessageQueue& queue) {
this->messageQueue = &queue;
}
void RemoteLibrary::ProcessMessage(musik::core::runtime::IMessage &message) {
if (message.Type() == MESSAGE_QUERY_COMPLETED) {
auto context = static_cast<QueryCompletedMessage*>(&message)->GetContext();
auto query = context->query;
this->QueryCompleted(context->query.get());
if (context->callback) {
context->callback(query);
}
}
}
musik::core::IIndexer* RemoteLibrary::Indexer() {
return nullptr;
}

View File

@ -0,0 +1,110 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2019 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
#include <core/config.h>
#include <core/db/Connection.h>
#include <core/library/ILibrary.h>
#include <core/library/IIndexer.h>
#include <core/library/IQuery.h>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <string>
namespace musik { namespace core { namespace library {
class RemoteLibrary :
public ILibrary,
public musik::core::runtime::IMessageTarget,
public std::enable_shared_from_this<RemoteLibrary>
{
public:
static ILibraryPtr Create(std::string name, int id);
RemoteLibrary(const RemoteLibrary&) = delete;
virtual ~RemoteLibrary();
/* ILibrary */
virtual int Enqueue(
QueryPtr query,
unsigned int options = 0,
Callback = Callback()) override;
virtual musik::core::IIndexer *Indexer() override;
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 */
virtual void ProcessMessage(musik::core::runtime::IMessage &message) override;
private:
class QueryCompletedMessage;
struct QueryContext {
std::shared_ptr<musik::core::db::ISerializableQuery> query;
Callback callback;
};
using QueryContextPtr = std::shared_ptr<QueryContext>;
using QueryList = std::list<QueryContextPtr>;
RemoteLibrary(std::string name, int id); /* ctor */
void RunQuery(QueryContextPtr context, bool notify = true);
void ThreadProc();
QueryContextPtr GetNextQuery();
QueryList queryQueue;
musik::core::runtime::IMessageQueue* messageQueue;
std::string identifier;
int id;
std::string name;
std::thread* thread;
std::condition_variable_any queueCondition;
std::recursive_mutex mutex;
std::atomic<bool> exit;
};
} } }

View File

@ -35,7 +35,7 @@
#include "pch.hpp" #include "pch.hpp"
#include "MetadataMap.h" #include "MetadataMap.h"
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/library/LocalLibraryConstants.h> #include <core/library/LocalLibraryConstants.h>
#include <core/db/Connection.h> #include <core/db/Connection.h>
#include <core/db/Statement.h> #include <core/db/Statement.h>

View File

@ -34,14 +34,14 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/library/query/local/util/CategoryQueryUtil.h> #include <core/library/query/local/util/CategoryQueryUtil.h>
#include <core/library/metadata/MetadataMapList.h> #include <core/library/metadata/MetadataMapList.h>
#include <core/db/Connection.h> #include <core/db/Connection.h>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class AlbumListQuery : public musik::core::db::LocalQueryBase { class AlbumListQuery : public musik::core::db::QueryBase {
public: public:
AlbumListQuery( AlbumListQuery(
const std::string& filter = ""); const std::string& filter = "");

View File

@ -34,13 +34,13 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/library/query/local/util/SdkWrappers.h> #include <core/library/query/local/util/SdkWrappers.h>
#include <core/sdk/IValueList.h> #include <core/sdk/IValueList.h>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class AllCategoriesQuery : public musik::core::db::LocalQueryBase { class AllCategoriesQuery : public musik::core::db::QueryBase {
public: public:
using Result = SdkValueList::Shared; using Result = SdkValueList::Shared;

View File

@ -34,14 +34,14 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/library/track/TrackList.h> #include <core/library/track/TrackList.h>
#include <stdint.h> #include <stdint.h>
#include <vector> #include <vector>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class AppendPlaylistQuery : public musik::core::db::LocalQueryBase { class AppendPlaylistQuery : public musik::core::db::QueryBase {
public: public:
AppendPlaylistQuery( AppendPlaylistQuery(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,

View File

@ -34,7 +34,7 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/library/query/local/util/CategoryQueryUtil.h> #include <core/library/query/local/util/CategoryQueryUtil.h>
#include <core/library/query/local/util/SdkWrappers.h> #include <core/library/query/local/util/SdkWrappers.h>
#include <core/db/Statement.h> #include <core/db/Statement.h>
@ -45,7 +45,7 @@
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class CategoryListQuery : public musik::core::db::LocalQueryBase { class CategoryListQuery : public musik::core::db::QueryBase {
public: public:
using Result = SdkValueList::Shared; using Result = SdkValueList::Shared;

View File

@ -36,7 +36,7 @@
#include <core/db/Connection.h> #include <core/db/Connection.h>
#include <core/library/track/Track.h> #include <core/library/track/Track.h>
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/library/query/local/util/CategoryQueryUtil.h> #include <core/library/query/local/util/CategoryQueryUtil.h>
#include <core/library/query/local/util/TrackSort.h> #include <core/library/query/local/util/TrackSort.h>
#include <core/db/Statement.h> #include <core/db/Statement.h>

View File

@ -35,12 +35,12 @@
#pragma once #pragma once
#include <core/library/ILibrary.h> #include <core/library/ILibrary.h>
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/db/Connection.h> #include <core/db/Connection.h>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class DeletePlaylistQuery : public musik::core::db::LocalQueryBase { class DeletePlaylistQuery : public musik::core::db::QueryBase {
public: public:
DeletePlaylistQuery( DeletePlaylistQuery(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,

View File

@ -36,7 +36,7 @@
#include <core/db/Connection.h> #include <core/db/Connection.h>
#include <core/library/track/Track.h> #include <core/library/track/Track.h>
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include "TrackListQueryBase.h" #include "TrackListQueryBase.h"

View File

@ -34,11 +34,16 @@
#include "pch.hpp" #include "pch.hpp"
#include "LyricsQuery.h" #include "LyricsQuery.h"
#include <json.hpp>
using namespace musik::core::db; using namespace musik::core::db;
using namespace musik::core::db::local; using namespace musik::core::db::local;
using namespace musik::core::sdk; using namespace musik::core::sdk;
const std::string LyricsQuery::kQueryName = "LyricsQuery";
/* IQuery */
LyricsQuery::LyricsQuery(const std::string& trackExternalId) { LyricsQuery::LyricsQuery(const std::string& trackExternalId) {
this->trackExternalId = trackExternalId; this->trackExternalId = trackExternalId;
} }
@ -70,4 +75,30 @@ bool LyricsQuery::OnRun(musik::core::db::Connection &db) {
} }
return true; return true;
}
/* ISerializableQuery */
std::string LyricsQuery::SerializeQuery() {
nlohmann::json query;
query["name"] = this->Name();
query["options"] = {{ "trackExternalId", this->trackExternalId }};
return query.dump();
}
std::string LyricsQuery::SerializeResult() {
nlohmann::json query;
query["result"] = this->result;
return query.dump();
}
void LyricsQuery::DeserializeResult(const std::string& data) {
this->SetStatus(IQuery::Failed);
this->result = nlohmann::json::parse(data).value("result", "");
this->SetStatus(IQuery::Finished);
}
std::shared_ptr<LyricsQuery> LyricsQuery::DeserializeQuery(const std::string& data) {
nlohmann::json query = nlohmann::json::parse(data);
return std::make_shared<LyricsQuery>(query["options"].value("trackExternalId", ""));
} }

View File

@ -34,19 +34,27 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class LyricsQuery : public musik::core::db::LocalQueryBase { class LyricsQuery: public musik::core::db::QueryBase {
public: public:
static const std::string kQueryName;
LyricsQuery(const std::string& trackExternalId); LyricsQuery(const std::string& trackExternalId);
virtual ~LyricsQuery(); virtual ~LyricsQuery();
std::string Name() { return "LyricsQuery"; } /* IQuery */
std::string Name() { return kQueryName; }
virtual std::string GetResult(); virtual std::string GetResult();
/* ISerializableQuery */
virtual std::string SerializeQuery();
virtual std::string SerializeResult();
virtual void DeserializeResult(const std::string& data);
static std::shared_ptr<LyricsQuery> DeserializeQuery(const std::string& data);
protected: protected:
virtual bool OnRun(musik::core::db::Connection &db); virtual bool OnRun(musik::core::db::Connection &db);

View File

@ -34,11 +34,11 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class MarkTrackPlayedQuery: public musik::core::db::LocalQueryBase { class MarkTrackPlayedQuery: public musik::core::db::QueryBase {
public: public:
MarkTrackPlayedQuery(const int64_t trackId); MarkTrackPlayedQuery(const int64_t trackId);
virtual ~MarkTrackPlayedQuery(); virtual ~MarkTrackPlayedQuery();

View File

@ -34,7 +34,7 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/audio/PlaybackService.h> #include <core/audio/PlaybackService.h>
#include "TrackListQueryBase.h" #include "TrackListQueryBase.h"

View File

@ -34,12 +34,12 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/audio/PlaybackService.h> #include <core/audio/PlaybackService.h>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class PersistedPlayQueueQuery : public musik::core::db::LocalQueryBase { class PersistedPlayQueueQuery : public musik::core::db::QueryBase {
public: public:
static PersistedPlayQueueQuery* Save( static PersistedPlayQueueQuery* Save(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,

View File

@ -34,7 +34,7 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/library/track/TrackList.h> #include <core/library/track/TrackList.h>
#include <core/db/Connection.h> #include <core/db/Connection.h>
#include <core/library/ILibrary.h> #include <core/library/ILibrary.h>
@ -42,7 +42,7 @@
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class SavePlaylistQuery : public musik::core::db::LocalQueryBase { class SavePlaylistQuery : public musik::core::db::QueryBase {
public: public:
static std::shared_ptr<SavePlaylistQuery> Save( static std::shared_ptr<SavePlaylistQuery> Save(
musik::core::ILibraryPtr library, musik::core::ILibraryPtr library,

View File

@ -34,11 +34,11 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class SetTrackRatingQuery: public musik::core::db::LocalQueryBase { class SetTrackRatingQuery: public musik::core::db::QueryBase {
public: public:
SetTrackRatingQuery(int64_t trackId, int rating); SetTrackRatingQuery(int64_t trackId, int rating);
virtual ~SetTrackRatingQuery(); virtual ~SetTrackRatingQuery();

View File

@ -34,14 +34,14 @@
#pragma once #pragma once
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/db/Connection.h> #include <core/db/Connection.h>
#include <core/library/track/Track.h> #include <core/library/track/Track.h>
#include <core/library/track/TrackList.h> #include <core/library/track/TrackList.h>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class TrackListQueryBase : public musik::core::db::LocalQueryBase { class TrackListQueryBase : public musik::core::db::QueryBase {
public: public:
typedef std::shared_ptr<musik::core::TrackList> Result; typedef std::shared_ptr<musik::core::TrackList> Result;
typedef std::shared_ptr<std::set<size_t> > Headers; typedef std::shared_ptr<std::set<size_t> > Headers;

View File

@ -32,13 +32,13 @@
// //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#include "LocalQueryBase.h" #include <core/library/QueryBase.h>
#include <core/library/track/Track.h> #include <core/library/track/Track.h>
namespace musik { namespace core { namespace db { namespace local { namespace musik { namespace core { namespace db { namespace local {
class TrackMetadataQuery : public LocalQueryBase { class TrackMetadataQuery : public QueryBase {
public: public:
enum Type { Full, IdsOnly }; enum Type { Full, IdsOnly };

View File

@ -35,7 +35,7 @@
#include "pch.hpp" #include "pch.hpp"
#include "TrackList.h" #include "TrackList.h"
#include <core/library/query/local/LocalQueryBase.h> #include <core/library/QueryBase.h>
#include <core/library/track/LibraryTrack.h> #include <core/library/track/LibraryTrack.h>
#include <core/library/LocalLibraryConstants.h> #include <core/library/LocalLibraryConstants.h>
#include <core/library/track/Track.h> #include <core/library/track/Track.h>

View File

@ -38,6 +38,7 @@
#include <core/support/Auddio.h> #include <core/support/Auddio.h>
#include <core/support/Common.h> #include <core/support/Common.h>
#include <core/library/query/local/LyricsQuery.h> #include <core/library/query/local/LyricsQuery.h>
#include <core/library/RemoteLibrary.h>
#include <cursespp/App.h> #include <cursespp/App.h>
#include <cursespp/Screen.h> #include <cursespp/Screen.h>
#include <cursespp/ToastOverlay.h> #include <cursespp/ToastOverlay.h>
@ -71,6 +72,9 @@ LyricsLayout::LyricsLayout(PlaybackService& playback, ILibraryPtr library)
this->AddWindow(this->infoText); this->AddWindow(this->infoText);
this->LoadLyricsForCurrentTrack(); this->LoadLyricsForCurrentTrack();
this->remoteLibrary = musik::core::library::RemoteLibrary::Create("remote", 0xdeadbeef);
this->remoteLibrary->SetMessageQueue(Window::MessageQueue());
} }
void LyricsLayout::OnLayout() { void LyricsLayout::OnLayout() {
@ -137,7 +141,7 @@ void LyricsLayout::LoadLyricsForCurrentTrack() {
this->SetState(State::Loading); this->SetState(State::Loading);
auto trackExternalId = track->GetString("external_id"); auto trackExternalId = track->GetString("external_id");
auto lyricsDbQuery = std::make_shared<LyricsQuery>(trackExternalId); auto lyricsDbQuery = std::make_shared<LyricsQuery>(trackExternalId);
this->library->Enqueue(lyricsDbQuery, 0, [this, lyricsDbQuery, track](auto q) { this->remoteLibrary->Enqueue(lyricsDbQuery, 0, [this, lyricsDbQuery, track](auto q) {
auto localLyrics = lyricsDbQuery->GetResult(); auto localLyrics = lyricsDbQuery->GetResult();
if (localLyrics.size()) { if (localLyrics.size()) {
this->OnLyricsLoaded(track, localLyrics); this->OnLyricsLoaded(track, localLyrics);

View File

@ -28,9 +28,6 @@ namespace musik { namespace cube {
private: private:
enum class State: int { NotPlaying, Loading, Loaded, Failed }; enum class State: int { NotPlaying, Loading, Loaded, Failed };
void OnAdapterChanged(cursespp::SimpleScrollAdapter* adapter);
void OnSelectionChanged(cursespp::ListWindow* window, size_t index, size_t prev);
void OnPlaybackEvent(int playbackEvent);
void OnTrackChanged(size_t index, musik::core::TrackPtr track); void OnTrackChanged(size_t index, musik::core::TrackPtr track);
void OnLyricsLoaded(musik::core::TrackPtr track, const std::string& lyrics); void OnLyricsLoaded(musik::core::TrackPtr track, const std::string& lyrics);
@ -39,7 +36,7 @@ namespace musik { namespace cube {
void UpdateAdapter(const std::string& lyrics); void UpdateAdapter(const std::string& lyrics);
State state { State::NotPlaying }; State state { State::NotPlaying };
musik::core::ILibraryPtr library; musik::core::ILibraryPtr library, remoteLibrary;
musik::core::audio::PlaybackService& playback; musik::core::audio::PlaybackService& playback;
std::shared_ptr<cursespp::SimpleScrollAdapter> adapter; std::shared_ptr<cursespp::SimpleScrollAdapter> adapter;
std::shared_ptr<cursespp::ListWindow> listView; std::shared_ptr<cursespp::ListWindow> listView;