Make web remote base url configurable by a flag.

This commit is contained in:
John Maguire 2014-05-15 17:59:22 +02:00
parent 6537ba4a06
commit f88cf84bc2
12 changed files with 114 additions and 48 deletions

View File

@ -17,6 +17,7 @@
#include "closure.h"
#include <QApplication>
#include <QTimer>
#include "core/timeconstants.h"
@ -32,8 +33,28 @@ CallbackClosure::CallbackClosure(QObject* sender, const char* signal,
: ClosureBase(new ObjectHelper(sender, signal, this)),
callback_(callback) {}
CallbackClosure::CallbackClosure(std::function<void()> callback)
: ClosureBase(new ObjectHelper(this)),
callback_(callback) {}
void CallbackClosure::Invoke() { callback_(); }
MainThreadCallbackClosure::MainThreadCallbackClosure(
std::function<void()> callback)
: CallbackClosure(callback) {
helper_->moveToThread(QApplication::instance()->thread());
}
void MainThreadCallbackClosure::Invoke() {
Q_ASSERT(QThread::thread() == QApplication::instance()->thread());
CallbackClosure::Invoke();
}
void MainThreadCallbackClosure::DoNow() {
helper_->metaObject()->invokeMethod(helper_, "Invoked", Qt::QueuedConnection);
}
ObjectHelper* ClosureBase::helper() const { return helper_; }
ObjectHelper::ObjectHelper(QObject* sender, const char* signal,
@ -43,6 +64,9 @@ ObjectHelper::ObjectHelper(QObject* sender, const char* signal,
connect(sender, SIGNAL(destroyed()), SLOT(deleteLater()));
}
ObjectHelper::ObjectHelper(ClosureBase* closure)
: closure_(closure) {}
void ObjectHelper::Invoked() {
closure_->Invoke();
deleteLater();
@ -65,3 +89,7 @@ void DoInAMinuteOrSo(QObject* receiver, const char* slot) {
int msec = (60 + (qrand() % 60)) * kMsecPerSec;
DoAfter(receiver, slot, msec);
}
void RunOnMainThread(std::function<void()> callback) {
(new _detail::MainThreadCallbackClosure(callback))->DoNow();
}

View File

@ -53,8 +53,9 @@ class ObjectHelper : public QObject {
Q_OBJECT
public:
ObjectHelper(QObject* parent, const char* signal, ClosureBase* closure);
explicit ObjectHelper(ClosureBase* closure);
private slots:
public slots:
void Invoked();
private:
@ -138,6 +139,7 @@ class CallbackClosure : public ClosureBase {
public:
CallbackClosure(QObject* sender, const char* signal,
std::function<void()> callback);
explicit CallbackClosure(std::function<void()> callback);
virtual void Invoke();
@ -145,6 +147,14 @@ class CallbackClosure : public ClosureBase {
std::function<void()> callback_;
};
class MainThreadCallbackClosure : public CallbackClosure {
public:
explicit MainThreadCallbackClosure(std::function<void()> callback);
virtual void Invoke();
void DoNow();
};
} // namespace _detail
template <typename... Args>
@ -189,5 +199,6 @@ _detail::ClosureBase* NewClosure(QObject* sender, const char* signal,
void DoAfter(QObject* receiver, const char* slot, int msec);
void DoInAMinuteOrSo(QObject* receiver, const char* slot);
void RunOnMainThread(std::function<void()> callback);
#endif // CLOSURE_H

View File

@ -77,6 +77,29 @@ Application::Application(QObject* parent)
network_remote_(nullptr),
network_remote_helper_(nullptr),
scrobbler_(nullptr) {
}
Application::~Application() {
// It's important that the device manager is deleted before the database.
// Deleting the database deletes all objects that have been created in its
// thread, including some device library backends.
delete device_manager_;
device_manager_ = nullptr;
for (QObject* object : objects_in_threads_) {
object->deleteLater();
}
for (QThread* thread : threads_) {
thread->quit();
}
for (QThread* thread : threads_) {
thread->wait();
}
}
void Application::Init() {
tag_reader_client_ = new TagReaderClient(this);
MoveToNewThread(tag_reader_client_);
tag_reader_client_->Start();
@ -133,26 +156,6 @@ Application::Application(QObject* parent)
DoInAMinuteOrSo(database_, SLOT(DoBackup()));
}
Application::~Application() {
// It's important that the device manager is deleted before the database.
// Deleting the database deletes all objects that have been created in its
// thread, including some device library backends.
delete device_manager_;
device_manager_ = nullptr;
for (QObject* object : objects_in_threads_) {
object->deleteLater();
}
for (QThread* thread : threads_) {
thread->quit();
}
for (QThread* thread : threads_) {
thread->wait();
}
}
void Application::MoveToNewThread(QObject* object) {
QThread* thread = new QThread(this);

View File

@ -54,14 +54,18 @@ class Application : public QObject {
public:
static bool kIsPortable;
Application(QObject* parent = nullptr);
explicit Application(QObject* parent = nullptr);
~Application();
void Init();
const QString& language_name() const { return language_name_; }
// Same as language_name, but remove the region code at the end if there is
// one
QString language_without_region() const;
void set_language_name(const QString& name) { language_name_ = name; }
QString remote_base_url() const { return remote_base_url_; }
void set_remote_base_url(const QString& url) { remote_base_url_ = url; }
TagReaderClient* tag_reader_client() const { return tag_reader_client_; }
Database* database() const { return database_; }
@ -107,6 +111,7 @@ signals:
private:
QString language_name_;
QString remote_base_url_;
TagReaderClient* tag_reader_client_;
Database* database_;

View File

@ -63,6 +63,13 @@ const char* CommandlineOptions::kHelpText =
const char* CommandlineOptions::kVersionText = "Clementine %1";
namespace {
const char* kDefaultRemoteBaseUrl =
"https://dev-dot-clementine-data.appspot.com";
} // namespace
CommandlineOptions::CommandlineOptions(int argc, char** argv)
: argc_(argc),
argv_(argv),
@ -75,7 +82,8 @@ CommandlineOptions::CommandlineOptions(int argc, char** argv)
play_track_at_(-1),
show_osd_(false),
toggle_pretty_osd_(false),
log_levels_(logging::kDefaultLogLevels) {
log_levels_(logging::kDefaultLogLevels),
remote_base_url_(kDefaultRemoteBaseUrl) {
#ifdef Q_OS_DARWIN
// Remove -psn_xxx option that Mac passes when opened from Finder.
RemoveArg("-psn", 1);
@ -125,6 +133,7 @@ bool CommandlineOptions::Parse() {
{"verbose", no_argument, 0, Verbose},
{"log-levels", required_argument, 0, LogLevels},
{"version", no_argument, 0, Version},
{"remote-base-url", required_argument, 0, RemoteBaseUrl},
{0, 0, 0, 0}};
// Parse the arguments
@ -261,6 +270,10 @@ bool CommandlineOptions::Parse() {
if (!ok) play_track_at_ = -1;
break;
case RemoteBaseUrl:
remote_base_url_ = optarg;
break;
case '?':
default:
return false;

View File

@ -66,6 +66,7 @@ class CommandlineOptions {
QList<QUrl> urls() const { return urls_; }
QString language() const { return language_; }
QString log_levels() const { return log_levels_; }
QString remote_base_url() const { return remote_base_url_; }
QByteArray Serialize() const;
void Load(const QByteArray& serialized);
@ -84,7 +85,8 @@ class CommandlineOptions {
Version,
VolumeIncreaseBy,
VolumeDecreaseBy,
RestartOrPrevious
RestartOrPrevious,
RemoteBaseUrl,
};
QString tr(const char* source_text);
@ -107,6 +109,7 @@ class CommandlineOptions {
bool toggle_pretty_osd_;
QString language_;
QString log_levels_;
QString remote_base_url_;
QList<QUrl> urls_;
};

View File

@ -448,6 +448,8 @@ int main(int argc, char* argv[]) {
Application app;
app.set_language_name(language);
app.set_remote_base_url(options.remote_base_url());
app.Init();
Echonest::Config::instance()->setAPIKey("DFLFLJBUF4EGTXHIG");
Echonest::Config::instance()->setNetworkAccessManager(

View File

@ -11,30 +11,28 @@
namespace {
//const char* kRemoteEndpoint = "http://localhost:8080/channel/remote/%1";
const char* kRemoteEndpoint = "https://remote-dot-clementine-data.appspot.com/channel/remote/%1";
const char* kInitialPage = "https://remote-dot-clementine-data.appspot.com/channel/clementine";
const char* kInitialPagePath = "/channel/clementine";
const char* kRemoteEndpointPath = "/channel/remote/%1";
} // namespace
ClementineWebPage::ClementineWebPage(QObject* parent)
: QWebPage(parent) {
qLog(Debug) << Q_FUNC_INFO;
NewClosure(this, SIGNAL(loadFinished(bool)), [&]() {
NewClosure(this, SIGNAL(loadFinished(bool)), [=]() {
qLog(Debug) << Q_FUNC_INFO << "load finished" << totalBytes();
qLog(Debug) << mainFrame()->toHtml();
mainFrame()->evaluateJavaScript("window.setTimeout");
});
}
void ClementineWebPage::Init() {
QMetaObject::invokeMethod(this, "InitOnMainThread", Qt::QueuedConnection);
}
void ClementineWebPage::InitOnMainThread() {
Q_ASSERT(QThread::currentThread() == qApp->thread());
mainFrame()->load(QUrl(kInitialPage));
void ClementineWebPage::Init(const QString& base_url) {
RunOnMainThread([=]{
Q_ASSERT(QThread::currentThread() == qApp->thread());
base_url_ = base_url;
QUrl url(base_url_);
url.setPath(kInitialPagePath);
mainFrame()->load(url);
});
}
void ClementineWebPage::javaScriptConsoleMessage(
@ -45,7 +43,9 @@ void ClementineWebPage::javaScriptConsoleMessage(
bool ClementineWebPage::javaScriptConfirm(QWebFrame*, const QString& message) {
id_ = message;
qLog(Debug) << "id:" << message;
qLog(Debug) << QString(kRemoteEndpoint).arg(message);
QUrl url(base_url_);
url.setPath(QString(kRemoteEndpointPath).arg(message));
qLog(Debug) << url;
return true;
}

View File

@ -7,7 +7,7 @@ class ClementineWebPage : public QWebPage {
public:
explicit ClementineWebPage(QObject* parent = nullptr);
void Init();
void Init(const QString& base_url);
const QString id() const { return id_; }
public slots:
@ -17,9 +17,6 @@ class ClementineWebPage : public QWebPage {
void Connected();
void MessageReceived(const pb::remote::Message& msg);
private slots:
void InitOnMainThread();
protected:
// For OOB communication for controlling the appengine channel.
virtual bool javaScriptConfirm(QWebFrame*, const QString& message);
@ -31,4 +28,5 @@ class ClementineWebPage : public QWebPage {
private:
QString id_;
QString base_url_;
};

View File

@ -75,7 +75,7 @@ void NetworkRemote::SetupServer() {
connect(server_ipv6_.get(), SIGNAL(newConnection()), this,
SLOT(AcceptConnection()));
connect(web_channel_.get(), SIGNAL(Connected()), SLOT(AcceptWebConnection()));
web_channel_->Init();
web_channel_->Init(app_->remote_base_url());
}
void NetworkRemote::StartServer() {

View File

@ -24,7 +24,7 @@ class RemoteClient : public QObject {
signals:
void Parse(const pb::remote::Message& msg);
private:
protected:
Application* app_;
bool downloader_;
};

View File

@ -2,6 +2,7 @@
#include <QByteArray>
#include "core/application.h"
#include "core/closure.h"
#include "core/logging.h"
#include "core/network.h"
@ -9,8 +10,7 @@
namespace {
//const char* kEndpoint = "http://localhost:8080/channel/clementine/push/%1";
const char* kEndpoint = "https://remote-dot-clementine-data.appspot.com/channel/clementine/push/%1";
const char* kEndpointPath = "/channel/clementine/push/%1";
} // namespace
@ -29,8 +29,11 @@ void WebRemoteClient::SendData(pb::remote::Message* msg) {
qLog(Debug) << "Sending:" << msg->DebugString().c_str();
std::string data = msg->SerializeAsString();
QByteArray base64 = QByteArray(data.data(), data.size()).toBase64();
QNetworkRequest request = QNetworkRequest(
QUrl(QString(kEndpoint).arg(web_channel_->id())));
QUrl url(app_->remote_base_url());
url.setPath(QString(kEndpointPath).arg(web_channel_->id()));
QNetworkRequest request = QNetworkRequest(url);
QNetworkReply* reply = network_->post(request, base64);
NewClosure(reply, SIGNAL(finished()),
this, SLOT(SendDataFinished(QNetworkReply*)), reply);