mirror of
https://github.com/clangen/musikcube.git
synced 2024-10-02 04:52:32 +00:00
Additional scaffolding.
This commit is contained in:
parent
31c8505a76
commit
e64a748371
@ -63,6 +63,7 @@ set(CORE_SOURCES
|
||||
./support/Duration.cpp
|
||||
./support/Common.cpp
|
||||
./support/LastFm.cpp
|
||||
./support/PiggyDebugBackend.cpp
|
||||
./support/Playback.cpp
|
||||
./support/Preferences.cpp
|
||||
./support/PreferenceKeys.cpp
|
||||
|
@ -36,8 +36,6 @@
|
||||
|
||||
#include <musikcore/net/PiggyWebSocketClient.h>
|
||||
#include <musikcore/support/Common.h>
|
||||
#include <musikcore/support/PreferenceKeys.h>
|
||||
#include <musikcore/support/Preferences.h>
|
||||
#include <musikcore/runtime/Message.h>
|
||||
#include <musikcore/version.h>
|
||||
|
||||
@ -50,43 +48,33 @@ using ClientMessage = PiggyWebSocketClient::ClientMessage;
|
||||
using Connection = PiggyWebSocketClient::Connection;
|
||||
using Message = PiggyWebSocketClient::Message;
|
||||
|
||||
static const int64_t kLatencyTimeoutMs = 30000;
|
||||
static const int64_t kPingIntervalMs = 10000;
|
||||
static const int kPingMessage = 6000;
|
||||
static const bool kDisableOfflineQueue = true;
|
||||
static std::atomic<int> nextMessageId(0);
|
||||
|
||||
static inline std::string generateMessageId() {
|
||||
return "integrated-websocket-client-" + std::to_string(nextMessageId.fetch_add(1));
|
||||
static inline std::string generateSessionId() {
|
||||
return "musikcube-" + std::to_string(nextMessageId.fetch_add(1));
|
||||
}
|
||||
|
||||
// static inline std::string createPingRequest() {
|
||||
// const nlohmann::json authRequestJson = {
|
||||
// { "name", "ping" },
|
||||
// { "type" , "request" },
|
||||
// { "id", generateMessageId() },
|
||||
// { "device_id", "remote-random-device" },
|
||||
// { "options", nlohmann::json() }
|
||||
// };
|
||||
// return authRequestJson.dump();
|
||||
// }
|
||||
static inline std::string createPingJson(const std::string& sessionId) {
|
||||
const nlohmann::json authRequestJson = {
|
||||
{ "name", "ping" },
|
||||
{ "sessionId", sessionId },
|
||||
{ "data", nlohmann::json() }
|
||||
};
|
||||
return authRequestJson.dump();
|
||||
}
|
||||
|
||||
// static inline bool extractRawQueryResult(
|
||||
// nlohmann::json& responseJson, std::string& rawResult)
|
||||
// {
|
||||
// if (responseJson["name"].get<std::string>() != "send_raw_query") {
|
||||
// return false;
|
||||
// }
|
||||
// rawResult = responseJson["options"]["raw_query_data"].get<std::string>();
|
||||
// return true;
|
||||
// }
|
||||
|
||||
PiggyWebSocketClient::PiggyWebSocketClient(IMessageQueue* messageQueue, Listener* listener)
|
||||
: messageQueue(nullptr) {
|
||||
PiggyWebSocketClient::PiggyWebSocketClient(IMessageQueue* messageQueue)
|
||||
: messageQueue(nullptr)
|
||||
, sessionId(generateSessionId()) {
|
||||
this->SetMessageQueue(messageQueue);
|
||||
|
||||
rawClient = std::make_unique<RawWebSocketClient>(io);
|
||||
|
||||
this->listener = listener;
|
||||
|
||||
rawClient->SetMode(RawWebSocketClient::Mode::TLS);
|
||||
rawClient->SetMode(RawWebSocketClient::Mode::PlainText);
|
||||
|
||||
rawClient->SetOpenHandler([this](Connection connection) {
|
||||
this->SetState(State::Authenticating);
|
||||
@ -138,28 +126,24 @@ void PiggyWebSocketClient::SetDisconnected(ConnectionError errorCode) {
|
||||
this->SetState(State::Disconnected);
|
||||
}
|
||||
|
||||
std::string PiggyWebSocketClient::EnqueueMessage(Message message) {
|
||||
void PiggyWebSocketClient::EnqueueMessage(Message message) {
|
||||
std::unique_lock<decltype(this->mutex)> lock(this->mutex);
|
||||
if (kDisableOfflineQueue && this->state != State::Connected) {
|
||||
return "";
|
||||
}
|
||||
if (!message) {
|
||||
return "";
|
||||
return;
|
||||
}
|
||||
(*message)["sessionId"] = this->sessionId;
|
||||
if (this->state != State::Connected) {
|
||||
if (!kDisableOfflineQueue) {
|
||||
this->pendingMessages.push_back(message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto messageId = generateMessageId();
|
||||
messageIdToMessage[messageId] = message;
|
||||
if (this->state == State::Connected) {
|
||||
this->rawClient->Send(this->connection, message->dump());
|
||||
}
|
||||
return messageId;
|
||||
}
|
||||
|
||||
void PiggyWebSocketClient::Connect(
|
||||
const std::string& host,
|
||||
unsigned short port,
|
||||
const std::string& password,
|
||||
bool useTls)
|
||||
{
|
||||
void PiggyWebSocketClient::Connect(const std::string& host, unsigned short port, bool useTls) {
|
||||
auto newUri = "ws://" + host + ":" + std::to_string(port);
|
||||
if (newUri != this->uri ||
|
||||
useTls != this->useTls ||
|
||||
@ -185,12 +169,9 @@ void PiggyWebSocketClient::Reconnect() {
|
||||
io.restart();
|
||||
#endif
|
||||
|
||||
auto const prefs = Preferences::ForComponent(core::prefs::components::Settings);
|
||||
auto const timeout = prefs->GetInt(core::prefs::keys::RemoteLibraryLatencyTimeoutMs, 5000);
|
||||
|
||||
this->SetState(State::Connecting);
|
||||
|
||||
this->thread = std::make_unique<std::thread>([&, timeout]() {
|
||||
this->thread = std::make_unique<std::thread>([&]() {
|
||||
std::string uri;
|
||||
|
||||
{
|
||||
@ -203,7 +184,7 @@ void PiggyWebSocketClient::Reconnect() {
|
||||
? RawWebSocketClient::Mode::TLS
|
||||
: RawWebSocketClient::Mode::PlainText;
|
||||
rawClient->SetMode(mode);
|
||||
rawClient->SetPongTimeout(timeout);
|
||||
rawClient->SetPongTimeout(kLatencyTimeoutMs);
|
||||
rawClient->Connect(uri);
|
||||
rawClient->Run();
|
||||
}
|
||||
@ -228,27 +209,17 @@ void PiggyWebSocketClient::Disconnect() {
|
||||
|
||||
void PiggyWebSocketClient::InvalidatePendingMessages() {
|
||||
std::unique_lock<decltype(this->mutex)> lock(this->mutex);
|
||||
|
||||
// for (auto& kv : this->messageIdToMessage) {
|
||||
// this->listener->OnClientQueryFailed(
|
||||
// this, kv.first, kv.second, QueryError::Disconnected);
|
||||
// }
|
||||
|
||||
this->messageIdToMessage.clear();
|
||||
this->pendingMessages.clear();
|
||||
}
|
||||
|
||||
void PiggyWebSocketClient::SendPendingMessages() {
|
||||
std::unique_lock<decltype(this->mutex)> lock(this->mutex);
|
||||
|
||||
// for (auto& kv : this->messageIdToMessage) {
|
||||
// auto messageId = kv.first;
|
||||
// auto query = kv.second;
|
||||
// if (query) {
|
||||
// this->rawClient->Send(
|
||||
// this->connection,
|
||||
// createSendRawQueryRequest(query->SerializeQuery(), messageId));
|
||||
// }
|
||||
// }
|
||||
for (auto& message : this->pendingMessages) {
|
||||
this->rawClient->Send(this->connection, message->dump());
|
||||
}
|
||||
|
||||
this->pendingMessages.clear();
|
||||
}
|
||||
|
||||
void PiggyWebSocketClient::SetState(State state) {
|
||||
@ -270,7 +241,7 @@ void PiggyWebSocketClient::SetState(State state) {
|
||||
}
|
||||
|
||||
this->state = state;
|
||||
this->listener->OnClientStateChanged(this, state, oldState);
|
||||
this->StateChanged(this, state, oldState);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,17 +255,17 @@ void PiggyWebSocketClient::SetMessageQueue(IMessageQueue* messageQueue) {
|
||||
this->messageQueue = messageQueue;
|
||||
if (this->messageQueue) {
|
||||
this->messageQueue->Register(this);
|
||||
// this->messageQueue->Post(Message::Create(this, kPingMessage), kPingIntervalMs);
|
||||
this->messageQueue->Post(runtime::Message::Create(this, kPingMessage), kPingIntervalMs);
|
||||
}
|
||||
}
|
||||
|
||||
/* IMessageTarget */
|
||||
void PiggyWebSocketClient::ProcessMessage(IMessage& message) {
|
||||
// if (message.Type() == kPingMessage) {
|
||||
// std::unique_lock<decltype(this->mutex)> lock(this->mutex);
|
||||
// if (this->state == State::Connected) {
|
||||
// this->rawClient->Send(this->connection, createPingRequest());
|
||||
// }
|
||||
// this->messageQueue->Post(Message::Create(this, kPingMessage), kPingIntervalMs);
|
||||
// }
|
||||
if (message.Type() == kPingMessage) {
|
||||
std::unique_lock<decltype(this->mutex)> lock(this->mutex);
|
||||
if (this->state == State::Connected) {
|
||||
this->rawClient->Send(this->connection, createPingJson(this->sessionId));
|
||||
}
|
||||
this->messageQueue->Post(runtime::Message::Create(this, kPingMessage), kPingIntervalMs);
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,10 @@
|
||||
#include <musikcore/net/RawWebSocketClient.h>
|
||||
#include <musikcore/runtime/IMessageQueue.h>
|
||||
|
||||
#include <sigslot/sigslot.h>
|
||||
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <deque>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
@ -66,36 +68,21 @@ namespace musik { namespace core { namespace net {
|
||||
|
||||
enum class ConnectionError : int {
|
||||
None = 0,
|
||||
InvalidPassword = 1,
|
||||
IncompatibleVersion = 2,
|
||||
ConnectionFailed = 3,
|
||||
ClosedByServer = 4,
|
||||
ConnectionFailed = 1,
|
||||
ClosedByServer = 2,
|
||||
};
|
||||
|
||||
class Listener {
|
||||
public:
|
||||
using Client = PiggyWebSocketClient;
|
||||
using State = Client::State;
|
||||
virtual void OnClientStateChanged(Client* client, State newState, State oldState) = 0;
|
||||
};
|
||||
|
||||
PiggyWebSocketClient(
|
||||
musik::core::runtime::IMessageQueue* messageQueue,
|
||||
Listener* listener);
|
||||
sigslot::signal3<PiggyWebSocketClient*, State, State> StateChanged;
|
||||
|
||||
PiggyWebSocketClient(musik::core::runtime::IMessageQueue* messageQueue);
|
||||
PiggyWebSocketClient(const PiggyWebSocketClient&) = delete;
|
||||
virtual ~PiggyWebSocketClient();
|
||||
|
||||
void Connect(
|
||||
const std::string& host,
|
||||
unsigned short port,
|
||||
const std::string& password,
|
||||
bool useTls);
|
||||
|
||||
void Connect(const std::string& host, unsigned short port = 8347, bool useTls = false);
|
||||
void Reconnect();
|
||||
void Disconnect();
|
||||
|
||||
std::string EnqueueMessage(Message message);
|
||||
void EnqueueMessage(Message message);
|
||||
|
||||
State ConnectionState() const;
|
||||
ConnectionError LastConnectionError() const;
|
||||
@ -112,16 +99,16 @@ namespace musik { namespace core { namespace net {
|
||||
|
||||
ClientPtr rawClient;
|
||||
Connection connection;
|
||||
const std::string& sessionId;
|
||||
boost::asio::io_service io;
|
||||
std::unique_ptr<std::thread> thread;
|
||||
mutable std::recursive_mutex mutex;
|
||||
bool useTls{ false };
|
||||
std::string uri;
|
||||
std::unordered_map<std::string, Message> messageIdToMessage;
|
||||
std::deque<Message> pendingMessages;
|
||||
std::atomic<bool> quit{ false };
|
||||
ConnectionError connectionError{ ConnectionError::None };
|
||||
State state{ State::Disconnected };
|
||||
Listener* listener{ nullptr };
|
||||
musik::core::runtime::IMessageQueue* messageQueue;
|
||||
};
|
||||
|
||||
|
58
src/musikcore/support/PiggyDebugBackend.cpp
Normal file
58
src/musikcore/support/PiggyDebugBackend.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004-2021 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 "PiggyDebugBackend.h"
|
||||
|
||||
using namespace musik;
|
||||
|
||||
PiggyDebugBackend::PiggyDebugBackend(Client client): client(client) {
|
||||
}
|
||||
|
||||
PiggyDebugBackend::~PiggyDebugBackend() {
|
||||
}
|
||||
|
||||
void PiggyDebugBackend::verbose(const std::string& tag, const std::string& string) {
|
||||
}
|
||||
|
||||
void PiggyDebugBackend::info(const std::string& tag, const std::string& string) {
|
||||
}
|
||||
|
||||
void PiggyDebugBackend::warning(const std::string& tag, const std::string& string) {
|
||||
}
|
||||
|
||||
void PiggyDebugBackend::error(const std::string& tag, const std::string& string) {
|
||||
}
|
||||
|
58
src/musikcore/support/PiggyDebugBackend.h
Normal file
58
src/musikcore/support/PiggyDebugBackend.h
Normal file
@ -0,0 +1,58 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2004-2021 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 <memory>
|
||||
#include <musikcore/debug.h>
|
||||
#include <musikcore/net/PiggyWebSocketClient.h>
|
||||
|
||||
namespace musik {
|
||||
|
||||
class PiggyDebugBackend : public musik::debug::IBackend {
|
||||
public:
|
||||
using Client = std::shared_ptr<musik::core::net::PiggyWebSocketClient>;
|
||||
|
||||
PiggyDebugBackend(Client client);
|
||||
virtual ~PiggyDebugBackend() override;
|
||||
virtual void verbose(const std::string& tag, const std::string& string) override;
|
||||
virtual void info(const std::string& tag, const std::string& string) override;
|
||||
virtual void warning(const std::string& tag, const std::string& string) override;
|
||||
virtual void error(const std::string& tag, const std::string& string) override;
|
||||
|
||||
private:
|
||||
Client client;
|
||||
};
|
||||
|
||||
}
|
@ -58,6 +58,8 @@
|
||||
#include <musikcore/support/PreferenceKeys.h>
|
||||
#include <musikcore/sdk/constants.h>
|
||||
#include <musikcore/support/Common.h>
|
||||
#include <musikcore/net/PiggyWebSocketClient.h>
|
||||
#include <musikcore/support/PiggyDebugBackend.h>
|
||||
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@ -72,6 +74,7 @@
|
||||
using namespace musik;
|
||||
using namespace musik::core;
|
||||
using namespace musik::core::audio;
|
||||
using namespace musik::core::net;
|
||||
using namespace musik::cube;
|
||||
using namespace cursespp;
|
||||
|
||||
@ -113,9 +116,13 @@ int main(int argc, char* argv[]) {
|
||||
std::string errorFn = core::GetDataDirectory() + "stderr.txt";
|
||||
freopen(errorFn.c_str(), "w", stderr);
|
||||
|
||||
auto piggyClient = std::make_shared<PiggyWebSocketClient>(&Window::MessageQueue());
|
||||
piggyClient->Connect("172.31.16.1");
|
||||
auto piggyLogger = new PiggyDebugBackend(piggyClient);
|
||||
|
||||
auto fileLogger = new debug::SimpleFileBackend();
|
||||
auto consoleLogger = new ConsoleLogger(Window::MessageQueue());
|
||||
debug::Start({ fileLogger, consoleLogger });
|
||||
debug::Start({ fileLogger, consoleLogger, piggyLogger });
|
||||
|
||||
plugin::Init();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user