Music Hub ..
A session-wide music playback service
qtbridge.cpp
Go to the documentation of this file.
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
17 * Thomas Voß <thomas.voss@canonical.com>
18 */
19
20#include "qtbridge.h"
21
22#include<QCoreApplication>
23#include<QNetworkAccessManager>
24#include<QNetworkRequest>
25#include<QNetworkReply>
26#include<QThread>
27#include<QDebug>
28
29namespace
30{
31QCoreApplication* app = nullptr;
32}
33
34namespace qt
35{
36namespace core
37{
38namespace world
39{
40namespace detail
41{
43{
44 static QEvent::Type event_type = static_cast<QEvent::Type>(QEvent::registerEventType());
45 return event_type;
46}
47
48class TaskEvent : public QEvent
49{
50public:
51 TaskEvent(const std::function<void()>& task)
53 task(task)
54 {
55 }
56
57 void run()
58 {
59 try
60 {
61 task();
62 promise.set_value();
63 } catch(...)
64 {
65 promise.set_exception(std::current_exception());
66 }
67 }
68
69 std::future<void> get_future()
70 {
71 return promise.get_future();
72 }
73
74private:
75 std::function<void()> task;
76 std::promise<void> promise;
77};
78
79class TaskHandler : public QObject
80{
81 Q_OBJECT
82
83public:
84 TaskHandler(QObject* parent) : QObject(parent)
85 {
86 }
87
88 bool event(QEvent* e);
89};
90
91
92
93void createCoreApplicationInstanceWithArgs(int argc, char** argv)
94{
95 app = new QCoreApplication(argc, argv);
96}
97
99{
100 delete app;
101}
102
103QCoreApplication* coreApplicationInstance()
104{
105 return app;
106}
107
109{
110 static TaskHandler* instance = new TaskHandler(coreApplicationInstance());
111 return instance;
112}
113
115{
116 if (e->type() != qt_core_world_task_event_type())
117 return QObject::event(e);
118
119 auto te = dynamic_cast<TaskEvent*>(e);
120 if (te)
121 {
122 te->run();
123 return true;
124 }
125
126 return false;
127}
128}
129
130void build_and_run(int argc, char** argv, const std::function<void()>& ready)
131{
132 QThread::currentThread();
133 if (QCoreApplication::instance() != nullptr)
134 throw std::runtime_error(
135 "qt::core::world::build_and_run: "
136 "There is already a QCoreApplication running.");
137
139
140 detail::task_handler()->moveToThread(
142
143 // Signal to other worlds that we are good to go.
144 ready();
145
147
148 // Someone has called quit and we clean up on the correct thread here.
150}
151
153{
154 enter_with_task([]()
155 {
156 // We make sure that all tasks have completed before quitting the app.
157 QEventLoopLocker locker;
158 }).wait_for(std::chrono::seconds{1});
159}
160
161std::future<void> enter_with_task(const std::function<void()>& task)
162{
163 QCoreApplication* instance = QCoreApplication::instance();
164
165 if (!instance)
166 {
167 throw std::runtime_error("Qt world has not been built before calling this function.");
168 }
169
170 detail::TaskEvent* te = new detail::TaskEvent(task);
171 auto future = te->get_future();
172
173 // We hand over ownership of te here. The event is deleted later after it has
174 // been processed by the event loop.
175 instance->postEvent(detail::task_handler(), te);
176
177 return future;
178}
179
180}
181}
182}
183
184#include "qtbridge.moc"
TaskEvent(const std::function< void()> &task)
Definition: qtbridge.cpp:51
std::future< void > get_future()
Definition: qtbridge.cpp:69
Definition: player.h:34
void createCoreApplicationInstanceWithArgs(int argc, char **argv)
Definition: qtbridge.cpp:93
QCoreApplication * coreApplicationInstance()
Definition: qtbridge.cpp:103
QEvent::Type qt_core_world_task_event_type()
Definition: qtbridge.cpp:42
void destroyCoreApplicationInstace()
Definition: qtbridge.cpp:98
TaskHandler * task_handler()
Definition: qtbridge.cpp:108
void build_and_run(int argc, char **argv, const std::function< void()> &ready)
Sets up the Qt core world and executes its event loop. Blocks until destroy() is called.
Definition: qtbridge.cpp:130
void destroy()
Destroys the Qt core world and quits its event loop.
Definition: qtbridge.cpp:152
std::future< void > enter_with_task(const std::function< void()> &task)
Enters the Qt core world and schedules the given task for execution.
Definition: qtbridge.cpp:161
Definition: qtbridge.cpp:35