obsolete TODO items
[harmattan/cameraplus] / src / cameraresources.cpp
1 /*!
2  * This file is part of CameraPlus.
3  *
4  * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include "cameraresources.h"
22 #include <dbusconnectioneventloop.h>
23 #include <QDebug>
24
25 CameraResources::CameraResources(QObject *parent) :
26   QObject(parent),
27   m_worker(new CameraResourcesWorker) {
28
29   m_worker->moveToThread(&m_thread);
30   DBUSConnectionEventLoop::getInstance().moveToThread(&m_thread);
31
32   QObject::connect(&m_thread, SIGNAL(started()), m_worker, SLOT(init()));
33   m_thread.start();
34
35   qRegisterMetaType<CameraResources::Mode>("CameraResources::Mode");
36   qRegisterMetaType<CameraResources::ResourceType>("CameraResources::ResourceType");
37   qRegisterMetaType<bool *>("bool *");
38
39   QObject::connect(m_worker, SIGNAL(acquiredChanged()), this, SIGNAL(acquiredChanged()));
40   QObject::connect(m_worker, SIGNAL(hijackedChanged()), this, SIGNAL(hijackedChanged()));
41   QObject::connect(m_worker, SIGNAL(updated()), this, SIGNAL(updated()));
42 }
43
44 CameraResources::~CameraResources() {
45   m_thread.quit();
46   m_thread.wait();
47
48   delete m_worker;
49   m_worker = 0;
50 }
51
52 bool CameraResources::isResourceGranted(const ResourceType& resource) {
53   bool ok = false;
54
55   QMetaObject::invokeMethod(m_worker, "isResourceGranted", Qt::BlockingQueuedConnection,
56                             Q_ARG(bool *, &ok), Q_ARG(CameraResources::ResourceType, resource));
57
58   return ok;
59 }
60
61 bool CameraResources::acquire(const Mode& mode) {
62   bool ok = false;
63
64   QMetaObject::invokeMethod(m_worker, "acquire", Qt::BlockingQueuedConnection,
65                             Q_ARG(bool *, &ok), Q_ARG(CameraResources::Mode, mode));
66
67   return ok;
68 }
69
70 bool CameraResources::acquired() const {
71   bool ok = false;
72
73   QMetaObject::invokeMethod(m_worker, "acquired", Qt::BlockingQueuedConnection,
74                             Q_ARG(bool *, &ok));
75
76   return ok;
77 }
78
79 bool CameraResources::hijacked() const {
80   bool ok = false;
81
82   QMetaObject::invokeMethod(m_worker, "hijacked", Qt::BlockingQueuedConnection,
83                             Q_ARG(bool *, &ok));
84
85   return ok;
86 }
87
88 CameraResourcesWorker::CameraResourcesWorker(QObject *parent) :
89   QObject(parent),
90   m_set(0),
91   m_mode(CameraResources::None),
92   m_acquired(false),
93   m_acquiring(false),
94   m_hijacked(false) {
95
96 }
97
98 CameraResourcesWorker::~CameraResourcesWorker() {
99   bool ok;
100
101   acquire(&ok, CameraResources::None);
102 }
103
104 void CameraResourcesWorker::init() {
105   m_set = new ResourcePolicy::ResourceSet("camera", this);
106   m_set->setAlwaysReply();
107
108   QObject::connect(m_set, SIGNAL(resourcesReleased()), this, SLOT(resourcesReleased()));
109   QObject::connect(m_set, SIGNAL(lostResources()), this, SLOT(lostResources()));
110   QObject::connect(m_set, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>&)),
111                    this, SLOT(resourcesGranted(const QList<ResourcePolicy::ResourceType>&)));
112   QObject::connect(m_set, SIGNAL(resourcesDenied()), this, SLOT(resourcesDenied()));
113
114   if (!m_set->initAndConnect()) {
115     qCritical() << "Failed to connect to resource policy engine";
116   }
117 }
118
119 void CameraResourcesWorker::resourcesReleased() {
120   setHijacked(false);
121   setAcquired(false);
122
123   m_acquiring = false;
124 }
125
126 void CameraResourcesWorker::lostResources() {
127   setAcquired(false);
128   setHijacked(true);
129
130   m_acquiring = false;
131 }
132
133 void CameraResourcesWorker::resourcesGranted(const QList<ResourcePolicy::ResourceType>& optional) {
134   Q_UNUSED(optional);
135
136   if (!m_acquiring) {
137     // This can happen when:
138     // 1) We lose/gain optional resources.
139     // 2) A higher priority application releases resources back.
140     emit updated();
141   }
142
143   m_acquiring = false;
144
145   setAcquired(true);
146   setHijacked(false);
147 }
148
149 void CameraResourcesWorker::resourcesDenied() {
150   setAcquired(false);
151   setHijacked(true);
152
153   m_acquiring = false;
154 }
155
156 QList<ResourcePolicy::ResourceType> CameraResourcesWorker::listSet() {
157   QList<ResourcePolicy::Resource *> resources = m_set->resources();
158
159   QList<ResourcePolicy::ResourceType> set;
160
161   foreach (ResourcePolicy::Resource *r, resources) {
162     set << r->type();
163   }
164
165   return set;
166 }
167
168 void CameraResourcesWorker::acquire(bool *ok, const CameraResources::Mode& mode) {
169   if (mode == m_mode) {
170     *ok = true;
171     return;
172   }
173
174   m_mode = mode;
175
176   *ok = false;
177
178   switch (m_mode) {
179   case CameraResources::None:
180     *ok = release();
181     break;
182
183   case CameraResources::Image:
184     *ok = updateSet(QList<ResourcePolicy::ResourceType>()
185                     << ResourcePolicy::VideoPlaybackType
186                     << ResourcePolicy::VideoRecorderType
187                     << ResourcePolicy::ScaleButtonType
188                     << ResourcePolicy::SnapButtonType);
189     break;
190
191   case CameraResources::Video:
192     *ok = updateSet(QList<ResourcePolicy::ResourceType>()
193                     << ResourcePolicy::VideoPlaybackType
194                     << ResourcePolicy::VideoRecorderType
195                     << ResourcePolicy::ScaleButtonType
196                     << ResourcePolicy::SnapButtonType);
197     break;
198
199   case CameraResources::Recording:
200     *ok = updateSet(QList<ResourcePolicy::ResourceType>()
201                     << ResourcePolicy::VideoPlaybackType
202                     << ResourcePolicy::VideoRecorderType
203                     << ResourcePolicy::ScaleButtonType
204                     << ResourcePolicy::SnapButtonType,
205                     QList<ResourcePolicy::ResourceType>()
206                     << ResourcePolicy::AudioRecorderType
207                     << ResourcePolicy::AudioPlaybackType);
208     break;
209
210   case CameraResources::PostCapture:
211     *ok = updateSet(QList<ResourcePolicy::ResourceType>(),
212                     QList<ResourcePolicy::ResourceType>()
213                     << ResourcePolicy::ScaleButtonType);
214     break;
215
216   default:
217     qWarning() << "Unknown mode" << mode;
218
219     *ok = false;
220   }
221 }
222
223 void CameraResourcesWorker::acquired(bool *ok) {
224   *ok = m_acquired;
225 }
226
227 void CameraResourcesWorker::hijacked(bool *ok) {
228   *ok = m_hijacked;
229 }
230
231 bool CameraResourcesWorker::updateSet(const QList<ResourcePolicy::ResourceType>& required,
232                                       const QList<ResourcePolicy::ResourceType>& optional) {
233
234
235   QList<ResourcePolicy::ResourceType> set = listSet();
236
237   foreach (ResourcePolicy::ResourceType r, set) {
238     if (required.indexOf(r) != -1) {
239       m_set->resource(r)->setOptional(false);
240     }
241     else if (optional.indexOf(r) != -1) {
242       m_set->resource(r)->setOptional(true);
243     }
244     else {
245       m_set->deleteResource(r);
246     }
247   }
248
249   foreach (ResourcePolicy::ResourceType r, required) {
250     m_set->addResource(r);
251   }
252
253   foreach (ResourcePolicy::ResourceType r, optional) {
254     m_set->addResource(r);
255     ResourcePolicy::Resource *res = m_set->resource(r);
256     if (res) {
257       res->setOptional(true);
258     }
259   }
260
261   if (m_set->contains(ResourcePolicy::AudioPlaybackType)) {
262     bool isOptional = m_set->resource(ResourcePolicy::AudioPlaybackType)->isOptional();
263
264     ResourcePolicy::AudioResource *audio = new ResourcePolicy::AudioResource("camera");
265     audio->setProcessID(QCoreApplication::applicationPid());
266     audio->setOptional(isOptional);
267     m_set->addResourceObject(audio);
268   }
269
270   m_acquiring = true;
271
272   m_set->update();
273   m_set->acquire();
274
275   while (m_acquiring) {
276     QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
277   }
278
279   return m_acquired;
280 }
281
282 bool CameraResourcesWorker::release() {
283   m_acquiring = true;
284
285   m_set->release();
286
287   while (m_acquiring) {
288     QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
289   }
290
291   m_mode = CameraResources::None;
292
293   return true;
294 }
295
296 void CameraResourcesWorker::setAcquired(bool acquired) {
297   if (m_acquired != acquired) {
298     m_acquired = acquired;
299     emit acquiredChanged();
300   }
301 }
302
303 void CameraResourcesWorker::setHijacked(bool hijacked) {
304   if (m_hijacked != hijacked) {
305     m_hijacked = hijacked;
306     emit hijackedChanged();
307   }
308 }
309
310 void CameraResourcesWorker::isResourceGranted(bool *ok,
311                                               const CameraResources::ResourceType& resource) {
312
313   ResourcePolicy::ResourceType rt = (ResourcePolicy::ResourceType)resource;
314
315   ResourcePolicy::Resource *r = m_set->resource(rt);
316   if (r) {
317     *ok = r->isGranted();
318   }
319 }