mirror of
https://github.com/clangen/musikcube.git
synced 2025-03-14 04:18:36 +00:00
Moved HttpClient into the SDK so plugins can use it as well. Required
some other minor restructuring.
This commit is contained in:
parent
d35e1d71d7
commit
b4f8bf60aa
@ -205,6 +205,7 @@
|
||||
<ClInclude Include="runtime\Message.h" />
|
||||
<ClInclude Include="runtime\MessageQueue.h" />
|
||||
<ClInclude Include="sdk\constants.h" />
|
||||
<ClInclude Include="sdk\HttpClient.h" />
|
||||
<ClInclude Include="sdk\IAnalyzer.h" />
|
||||
<ClInclude Include="sdk\IBuffer.h" />
|
||||
<ClInclude Include="sdk\IDecoder.h" />
|
||||
|
@ -543,5 +543,8 @@
|
||||
<ClInclude Include="support\LastFm.h">
|
||||
<Filter>src\support</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\HttpClient.h">
|
||||
<Filter>src\sdk\io</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -33,9 +33,6 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <core/version.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
@ -86,6 +83,9 @@ namespace musik { namespace core { namespace io {
|
||||
static size_t CurlHeaderCallback(char *buffer, size_t size, size_t nitems, void *userdata);
|
||||
static std::string DefaultUserAgent();
|
||||
|
||||
static void ReplaceAll(std::string& input, const std::string& find, const std::string& replace);
|
||||
static std::string Trim(const std::string &str);
|
||||
|
||||
void RunOnCurrentThread(Callback callback);
|
||||
|
||||
std::mutex mutex;
|
||||
@ -123,10 +123,12 @@ namespace musik { namespace core { namespace io {
|
||||
static const std::string PLATFORM = "linux";
|
||||
#endif
|
||||
|
||||
std::string version = boost::str(boost::format("%d.%d.%d")
|
||||
% VERSION_MAJOR % VERSION_MINOR % VERSION_PATCH);
|
||||
|
||||
return boost::str(boost::format("musikcube %s (%s)") % version % PLATFORM);
|
||||
return
|
||||
"musikcube " +
|
||||
std::to_string(VERSION_MAJOR) + "." +
|
||||
std::to_string(VERSION_MINOR) + "." +
|
||||
std::to_string(VERSION_PATCH) +
|
||||
"(" + PLATFORM + ")";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -152,18 +154,40 @@ namespace musik { namespace core { namespace io {
|
||||
return 0; /* ok! */
|
||||
}
|
||||
|
||||
template <typename T> /* copied from Common.h for SDK usage. */
|
||||
void HttpClient<T>::ReplaceAll(std::string& input, const std::string& find, const std::string& replace) {
|
||||
size_t pos = input.find(find);
|
||||
while (pos != std::string::npos) {
|
||||
input.replace(pos, find.size(), replace);
|
||||
pos = input.find(find, pos + replace.size());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string HttpClient<T>::Trim(const std::string &str) {
|
||||
std::string s(str);
|
||||
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t HttpClient<T>::CurlHeaderCallback(char *buffer, size_t size, size_t nitems, void *userdata) {
|
||||
HttpClient* stream = static_cast<HttpClient*>(userdata);
|
||||
|
||||
std::string header(buffer, size * nitems);
|
||||
|
||||
boost::algorithm::replace_all(header, "\r\n", "");
|
||||
ReplaceAll(header, "\r\n", "");
|
||||
|
||||
size_t splitAt = header.find_first_of(":");
|
||||
if (splitAt != std::string::npos) {
|
||||
std::string key = boost::trim_copy(header.substr(0, splitAt));
|
||||
std::string value = boost::trim_copy(header.substr(splitAt + 1));
|
||||
std::string key = Trim(header.substr(0, splitAt));
|
||||
std::string value = Trim(header.substr(splitAt + 1));
|
||||
stream->responseHeaders[key] = value;
|
||||
|
||||
if (stream->headersCb) {
|
||||
@ -205,13 +229,16 @@ namespace musik { namespace core { namespace io {
|
||||
|
||||
this->curl = curl_easy_init();
|
||||
|
||||
const std::string userAgent = this->userAgent.size()
|
||||
? userAgent : DefaultUserAgent();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, DefaultUserAgent().c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
@ -317,6 +344,12 @@ namespace musik { namespace core { namespace io {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::DefaultUserAgent(const std::string& userAgent) {
|
||||
this->userAgent = userAgent;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::Mode(Thread mode) {
|
||||
this->mode = mode;
|
||||
|
392
src/core/sdk/HttpClient.h
Normal file
392
src/core/sdk/HttpClient.h
Normal file
@ -0,0 +1,392 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
#include "constants.h"
|
||||
|
||||
namespace musik { namespace core { namespace sdk {
|
||||
template <typename T>
|
||||
class HttpClient: public std::enable_shared_from_this<HttpClient<T>> {
|
||||
public:
|
||||
enum class Thread { Current, Background };
|
||||
enum class HttpMethod { Get, Post };
|
||||
|
||||
using HttpHeaders = std::unordered_map<std::string, std::string>;
|
||||
using Callback = std::function<void(HttpClient<T>* caller, int, CURLcode)>;
|
||||
using DecoratorCallback = std::function<void(CURL*)>;
|
||||
using HeaderCallback = std::function<void(std::string, std::string)>;
|
||||
using CanceledCallback = std::function<void(HttpClient<T>* caller)>;
|
||||
|
||||
static std::shared_ptr<HttpClient<T>> Create(T&& stream) {
|
||||
return std::shared_ptr<HttpClient<T>>(new HttpClient<T>(std::move(stream)));
|
||||
}
|
||||
|
||||
~HttpClient();
|
||||
|
||||
HttpClient<T>& Url(const std::string& url);
|
||||
HttpClient<T>& Header(const std::string& key, const std::string& value);
|
||||
HttpClient<T>& Headers(HeaderCallback headersCb);
|
||||
HttpClient<T>& Decorator(DecoratorCallback decoratorCb);
|
||||
HttpClient<T>& Canceled(CanceledCallback canceledCb);
|
||||
HttpClient<T>& Mode(Thread mode);
|
||||
HttpClient<T>& PostBody(const std::string& postBody);
|
||||
HttpClient<T>& Method(HttpMethod mode);
|
||||
HttpClient<T>& UserAgent(const std::string& userAgent);
|
||||
|
||||
const T& Stream() const { return this->ostream; }
|
||||
const HttpHeaders& ResponseHeaders() const { return this->responseHeaders; }
|
||||
const HttpHeaders& RequestHeaders() const { return this->requestHeaders; }
|
||||
const std::string& Url() const { return this->url; }
|
||||
|
||||
HttpClient<T>& Run(Callback callback = Callback());
|
||||
void Wait();
|
||||
void Cancel();
|
||||
|
||||
private:
|
||||
HttpClient(T&& stream);
|
||||
|
||||
static size_t CurlWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata);
|
||||
static int CurlTransferCallback(void *ptr, curl_off_t downTotal, curl_off_t downNow, curl_off_t upTotal, curl_off_t upNow);
|
||||
static size_t CurlHeaderCallback(char *buffer, size_t size, size_t nitems, void *userdata);
|
||||
static std::string DefaultUserAgent();
|
||||
|
||||
static void ReplaceAll(std::string& input, const std::string& find, const std::string& replace);
|
||||
static std::string Trim(const std::string &str);
|
||||
|
||||
void RunOnCurrentThread(Callback callback);
|
||||
|
||||
std::mutex mutex;
|
||||
std::shared_ptr<std::thread> thread;
|
||||
|
||||
T ostream;
|
||||
std::string url;
|
||||
std::string postBody;
|
||||
std::string userAgent;
|
||||
HttpHeaders requestHeaders, responseHeaders;
|
||||
HeaderCallback headersCb;
|
||||
DecoratorCallback decoratorCb;
|
||||
CanceledCallback canceledCallback;
|
||||
bool cancel;
|
||||
Thread mode{ Thread::Background };
|
||||
HttpMethod method{ HttpMethod::Get };
|
||||
CURL* curl;
|
||||
|
||||
static std::mutex instanceMutex;
|
||||
static std::set<std::shared_ptr<HttpClient<T>>> instances;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::mutex HttpClient<T>::instanceMutex;
|
||||
|
||||
template <typename T>
|
||||
std::set<std::shared_ptr<HttpClient<T>>> HttpClient<T>::instances;
|
||||
|
||||
template <typename T>
|
||||
std::string HttpClient<T>::DefaultUserAgent() {
|
||||
#ifdef WIN32
|
||||
static const std::string PLATFORM = "win32";
|
||||
#elif defined __APPLE__
|
||||
static const std::string PLATFORM = "macos";
|
||||
#else
|
||||
static const std::string PLATFORM = "linux";
|
||||
#endif
|
||||
|
||||
return "musikcore sdk " +
|
||||
std::to_string(SdkVersion) + "." +
|
||||
"(" + PLATFORM + ")";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t HttpClient<T>::CurlWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
||||
if (ptr && userdata) {
|
||||
HttpClient* context = static_cast<HttpClient*>(userdata);
|
||||
if (context->cancel) {
|
||||
return 0; /* aborts */
|
||||
}
|
||||
context->ostream.write(ptr, size * nmemb);
|
||||
}
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int HttpClient<T>::CurlTransferCallback(
|
||||
void *ptr, curl_off_t downTotal, curl_off_t downNow, curl_off_t upTotal, curl_off_t upNow)
|
||||
{
|
||||
HttpClient* context = static_cast<HttpClient*>(ptr);
|
||||
if (context->cancel) {
|
||||
return -1; /* kill the stream */
|
||||
}
|
||||
return 0; /* ok! */
|
||||
}
|
||||
|
||||
template <typename T> /* copied from Common.h for SDK usage. */
|
||||
void HttpClient<T>::ReplaceAll(std::string& input, const std::string& find, const std::string& replace) {
|
||||
size_t pos = input.find(find);
|
||||
while (pos != std::string::npos) {
|
||||
input.replace(pos, find.size(), replace);
|
||||
pos = input.find(find, pos + replace.size());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string HttpClient<T>::Trim(const std::string &str) {
|
||||
std::string s(str);
|
||||
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t HttpClient<T>::CurlHeaderCallback(char *buffer, size_t size, size_t nitems, void *userdata) {
|
||||
HttpClient* stream = static_cast<HttpClient*>(userdata);
|
||||
|
||||
std::string header(buffer, size * nitems);
|
||||
|
||||
ReplaceAll(header, "\r\n", "");
|
||||
|
||||
size_t splitAt = header.find_first_of(":");
|
||||
if (splitAt != std::string::npos) {
|
||||
std::string key = Trim(header.substr(0, splitAt));
|
||||
std::string value = Trim(header.substr(splitAt + 1));
|
||||
stream->responseHeaders[key] = value;
|
||||
|
||||
if (stream->headersCb) {
|
||||
stream->headersCb(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return size * nitems;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>::HttpClient(T&& stream) {
|
||||
this->curl = nullptr;
|
||||
this->cancel = false;
|
||||
std::swap(this->ostream, stream);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>::~HttpClient() {
|
||||
std::unique_lock<std::mutex> lock(this->mutex);
|
||||
|
||||
if (this->curl) {
|
||||
curl_easy_cleanup(this->curl);
|
||||
}
|
||||
|
||||
if (this->thread && this->thread->joinable()) {
|
||||
this->cancel = true;
|
||||
this->thread->join();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::Run(Callback callback) {
|
||||
std::unique_lock<std::mutex> lock(this->mutex);
|
||||
|
||||
if (this->thread) {
|
||||
throw std::runtime_error("already started");
|
||||
}
|
||||
|
||||
this->curl = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, DefaultUserAgent().c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3000);
|
||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 7500);
|
||||
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 500);
|
||||
|
||||
if (this->decoratorCb) {
|
||||
this->decoratorCb(this->curl);
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &CurlWriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, &CurlTransferCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERDATA, this);
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &CurlHeaderCallback);
|
||||
|
||||
#if 0
|
||||
curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost");
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYPORT, 8080);
|
||||
#endif
|
||||
|
||||
if (this->requestHeaders.size()) {
|
||||
struct curl_slist* slist = nullptr;
|
||||
for (auto it : this->requestHeaders) {
|
||||
std::string header = it.first + ": " + it.second;
|
||||
slist = curl_slist_append(slist, header.c_str());
|
||||
}
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
|
||||
}
|
||||
|
||||
if (this->method == HttpMethod::Post) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
|
||||
if (this->postBody.size()) {
|
||||
curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, this->postBody.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == Thread::Background) {
|
||||
std::unique_lock<std::mutex> lock(instanceMutex);
|
||||
instances.insert(this->shared_from_this());
|
||||
|
||||
this->thread.reset(new std::thread([callback, this] {
|
||||
this->RunOnCurrentThread(callback);
|
||||
}));
|
||||
}
|
||||
else {
|
||||
this->RunOnCurrentThread(callback);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void HttpClient<T>::RunOnCurrentThread(Callback callback) {
|
||||
CURLcode curlCode = curl_easy_perform(this->curl);
|
||||
|
||||
if (this->cancel) {
|
||||
if (this->canceledCallback) {
|
||||
this->canceledCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
int httpStatus = 0;
|
||||
curl_easy_getinfo(this->curl, CURLINFO_RESPONSE_CODE, &httpStatus);
|
||||
|
||||
if (callback) {
|
||||
callback(this, httpStatus, curlCode);
|
||||
}
|
||||
|
||||
if (this->thread) {
|
||||
this->thread->detach();
|
||||
this->thread.reset();
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(instanceMutex);
|
||||
instances.erase(instances.find(this->shared_from_this()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void HttpClient<T>::Wait() {
|
||||
std::unique_lock<std::mutex> lock(this->mutex);
|
||||
|
||||
if (this->thread && this->thread->joinable()) {
|
||||
this->thread->join();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::Url(const std::string& url) {
|
||||
this->url = url;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::PostBody(const std::string& postBody) {
|
||||
this->postBody = postBody;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::Mode(Thread mode) {
|
||||
this->mode = mode;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::Method(HttpMethod method) {
|
||||
this->method = method;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::Header(const std::string& key, const std::string& value) {
|
||||
this->requestHeaders[key] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::Headers(HeaderCallback headersCb) {
|
||||
this->headersCb = headersCb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::Decorator(DecoratorCallback decoratorCb) {
|
||||
this->decoratorCb = decoratorCb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HttpClient<T>& HttpClient<T>::Canceled(CanceledCallback canceledCb) {
|
||||
this->canceledCb = canceledCb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void HttpClient<T>::Cancel() {
|
||||
std::unique_lock<std::mutex> lock(this->mutex);
|
||||
|
||||
if (this->thread) {
|
||||
this->cancel = true;
|
||||
if (this->thread->joinable()) {
|
||||
this->thread->join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} } }
|
@ -37,7 +37,7 @@
|
||||
#include <curl/curl.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <core/support/Preferences.h>
|
||||
#include <core/io/HttpClient.h>
|
||||
#include <core/sdk/HttpClient.h>
|
||||
#include <core/support/PreferenceKeys.h>
|
||||
#include <json.hpp>
|
||||
#include <sstream>
|
||||
@ -56,7 +56,7 @@ static const std::string ACCOUNT_LINK_URL_BASE = "http://www.last.fm/api/auth/?a
|
||||
using namespace musik;
|
||||
using namespace musik::core::prefs;
|
||||
|
||||
using LastFmClient = musik::core::io::HttpClient<std::stringstream>;
|
||||
using LastFmClient = musik::core::sdk::HttpClient<std::stringstream>;
|
||||
using Preferences = musik::core::Preferences;
|
||||
using Prefs = std::shared_ptr<Preferences>;
|
||||
|
||||
|
@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 42
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION "0.42.0"
|
@ -43,10 +43,10 @@
|
||||
|
||||
#include <core/sdk/IPlugin.h>
|
||||
#include <core/plugin/PluginFactory.h>
|
||||
#include <core/version.h>
|
||||
|
||||
#include <app/util/Hotkeys.h>
|
||||
#include <app/util/Messages.h>
|
||||
#include <app/version.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
@ -41,10 +41,10 @@
|
||||
#include <cursespp/DialogOverlay.h>
|
||||
|
||||
#include <core/runtime/Message.h>
|
||||
#include <core/version.h>
|
||||
|
||||
#include <app/util/Messages.h>
|
||||
#include <app/util/PreferenceKeys.h>
|
||||
#include <app/version.h>
|
||||
|
||||
using namespace nlohmann;
|
||||
using namespace musik::cube;
|
||||
|
28
src/musikcube/app/version.h
Normal file
28
src/musikcube/app/version.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 42
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION "0.42.0"
|
||||
|
||||
namespace musik {
|
||||
namespace cube {
|
||||
static inline std::string userAgent() {
|
||||
#ifdef WIN32
|
||||
static const std::string PLATFORM = "win32";
|
||||
#elif defined __APPLE__
|
||||
static const std::string PLATFORM = "macos";
|
||||
#else
|
||||
static const std::string PLATFORM = "linux";
|
||||
#endif
|
||||
return
|
||||
"musikcube " +
|
||||
std::to_string(VERSION_MAJOR) + "." +
|
||||
std::to_string(VERSION_MINOR) + "." +
|
||||
std::to_string(VERSION_PATCH) +
|
||||
"(" + PLATFORM + ")";
|
||||
}
|
||||
}
|
||||
}
|
@ -281,6 +281,7 @@ xcopy "$(SolutionDir)src\3rdparty\bin\win32\font\*.ttf" "$(TargetDir)fonts\" /Y
|
||||
<ClInclude Include="cursespp\Window.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="version.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\3rdparty\3rdparty.vcxproj">
|
||||
|
@ -391,6 +391,9 @@
|
||||
<ClInclude Include="app\overlay\ReassignHotkeyOverlay.h">
|
||||
<Filter>app\overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="version.h">
|
||||
<Filter>app</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="cursespp">
|
||||
|
Loading…
x
Reference in New Issue
Block a user