update() is a signal not a slot. Use the correct macro
[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 // TODO: video recording ?
26 // TODO: more resources ?
27 CameraResources::CameraResources(QObject *parent) :
28   QObject(parent),
29   m_worker(new CameraResourcesWorker) {
30
31   m_worker->moveToThread(&m_thread);
32   DBUSConnectionEventLoop::getInstance().moveToThread(&m_thread);
33
34   QObject::connect(&m_thread, SIGNAL(started()), m_worker, SLOT(init()));
35   m_thread.start();
36
37   qRegisterMetaType<CameraResources::Mode>("CameraResources::Mode");
38   qRegisterMetaType<CameraResources::ResourceType>("CameraResources::ResourceType");
39   qRegisterMetaType<bool *>("bool *");
40
41   QObject::connect(m_worker, SIGNAL(acquiredChanged()), this, SIGNAL(acquiredChanged()));
42   QObject::connect(m_worker, SIGNAL(hijackedChanged()), this, SIGNAL(hijackedChanged()));
43   QObject::connect(m_worker, SIGNAL(updated()), this, SIGNAL(updated()));
44 }
45
46 CameraResources::~CameraResources() {
47   m_thread.quit();
48   m_thread.wait();
49
50   delete m_worker;
51   m_worker = 0;
52 }
53
54 bool CameraResources::isResourceGranted(const ResourceType& resource) {
55   bool ok = false;
56
57   QMetaObject::invokeMethod(m_worker, "isResourceGranted", Qt::BlockingQueuedConnection,
58                             Q_ARG(bool *, &ok), Q_ARG(CameraResources::ResourceType, resource));
59
60   return ok;
61 }
62
63 bool CameraResources::acquire(const Mode& mode) {
64   bool ok = false;
65
66   QMetaObject::invokeMethod(m_worker, "acquire", Qt::BlockingQueuedConnection,
67                             Q_ARG(bool *, &ok), Q_ARG(CameraResources::Mode, mode));
68
69   return ok;
70 }
71
72 bool CameraResources::acquired() const {
73   bool ok = false;
74
75   QMetaObject::invokeMethod(m_worker, "acquired", Qt::BlockingQueuedConnection,
76                             Q_ARG(bool *, &ok));
77
78   return ok;
79 }
80
81 bool CameraResources::hijacked() const {
82   bool ok = false;
83
84   QMetaObject::invokeMethod(m_worker, "hijacked", Qt::BlockingQueuedConnection,
85                             Q_ARG(bool *, &ok));
86
87   return ok;
88 }
89
90 CameraResourcesWorker::CameraResourcesWorker(QObject *parent) :
91   QObject(parent),
92   m_set(0),
93   m_mode(CameraResources::None),
94   m_acquired(false),
95   m_acquiring(false),
96   m_hijacked(false) {
97
98 }
99
100 CameraResourcesWorker::~CameraResourcesWorker() {
101   bool ok;
102
103   acquire(&ok, CameraResources::None);
104 }
105
106 void CameraResourcesWorker::init() {
107   m_set = new ResourcePolicy::ResourceSet("camera", this);
108   m_set->setAlwaysReply();
109
110   QObject::connect(m_set, SIGNAL(resourcesReleased()), this, SLOT(resourcesReleased()));
111   QObject::connect(m_set, SIGNAL(lostResources()), this, SLOT(lostResources()));
112   QObject::connect(m_set, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>&)),
113                    this, SLOT(resourcesGranted(const QList<ResourcePolicy::ResourceType>&)));
114   QObject::connect(m_set, SIGNAL(resourcesDenied()), this, SLOT(resourcesDenied()));
115
116   if (!m_set->initAndConnect()) {
117     qCritical() << "Failed to connect to resource policy engine";
118   }
119 }
120
121 void CameraResourcesWorker::resourcesReleased() {
122   setHijacked(false);
123   setAcquired(false);
124
125   m_acquiring = false;
126 }
127
128 void CameraResourcesWorker::lostResources() {
129   setAcquired(false);
130   setHijacked(true);
131
132   m_acquiring = false;
133 }
134
135 void CameraResourcesWorker::resourcesGranted(const QList<ResourcePolicy::ResourceType>& optional) {
136   Q_UNUSED(optional);
137
138   if (!m_acquiring) {
139     // This can happen when:
140     // 1) We lose/gain optional resources.
141     // 2) A higher priority application releases resources back.
142     emit updated();
143   }
144
145   m_acquiring = false;
146
147   setAcquired(true);
148   setHijacked(false);
149 }
150
151 void CameraResourcesWorker::resourcesDenied() {
152   setAcquired(false);
153   setHijacked(true);
154
155   m_acquiring = false;
156 }
157
158 QList<ResourcePolicy::ResourceType> CameraResourcesWorker::listSet() {
159   QList<ResourcePolicy::Resource *> resources = m_set->resources();
160
161   QList<ResourcePolicy::ResourceType> set;
162
163   foreach (ResourcePolicy::Resource *r, resources) {
164     set << r->type();
165   }
166
167   return set;
168 }
169
170 void CameraResourcesWorker::acquire(bool *ok, const CameraResources::Mode& mode) {
171   if (mode == m_mode) {
172     *ok = true;
173     return;
174   }
175
176   m_mode = mode;
177
178   *ok = false;
179
180   switch (m_mode) {
181   case CameraResources::None:
182     *ok = release();
183     break;
184
185   case CameraResources::Image:
186     *ok = updateSet(QList<ResourcePolicy::ResourceType>()
187                     << ResourcePolicy::VideoPlaybackType
188                     << ResourcePolicy::VideoRecorderType
189                     << ResourcePolicy::ScaleButtonType
190                     << ResourcePolicy::SnapButtonType);
191     break;
192
193   case CameraResources::Video:
194     *ok = updateSet(QList<ResourcePolicy::ResourceType>()
195                     << ResourcePolicy::VideoPlaybackType
196                     << ResourcePolicy::VideoRecorderType
197                     << ResourcePolicy::ScaleButtonType
198                     << ResourcePolicy::SnapButtonType);
199     break;
200
201   case CameraResources::Recording:
202     *ok = updateSet(QList<ResourcePolicy::ResourceType>()
203                     << ResourcePolicy::VideoPlaybackType
204                     << ResourcePolicy::VideoRecorderType
205                     << ResourcePolicy::ScaleButtonType
206                     << ResourcePolicy::SnapButtonType,
207                     QList<ResourcePolicy::ResourceType>()
208                     << ResourcePolicy::AudioRecorderType
209                     << ResourcePolicy::AudioPlaybackType);
210     break;
211
212   case CameraResources::PostCapture:
213     *ok = updateSet(QList<ResourcePolicy::ResourceType>()
214                     << ResourcePolicy::VideoPlaybackType
215                     << ResourcePolicy::ScaleButtonType,
216                     QList<ResourcePolicy::ResourceType>()
217                     << ResourcePolicy::AudioPlaybackType);
218     break;
219
220   default:
221     qWarning() << "Unknown mode" << mode;
222
223     *ok = false;
224   }
225 }
226
227 void CameraResourcesWorker::acquired(bool *ok) {
228   *ok = m_acquired;
229 }
230
231 void CameraResourcesWorker::hijacked(bool *ok) {
232   *ok = m_hijacked;
233 }
234
235 bool CameraResourcesWorker::updateSet(const QList<ResourcePolicy::ResourceType>& required,
236                                       const QList<ResourcePolicy::ResourceType>& optional) {
237
238
239   QList<ResourcePolicy::ResourceType> set = listSet();
240
241   foreach (ResourcePolicy::ResourceType r, set) {
242     if (required.indexOf(r) != -1) {
243       m_set->resource(r)->setOptional(false);
244     }
245     else if (optional.indexOf(r) != -1) {
246       m_set->resource(r)->setOptional(true);
247     }
248     else {
249       m_set->deleteResource(r);
250     }
251   }
252
253   foreach (ResourcePolicy::ResourceType r, required) {
254     m_set->addResource(r);
255   }
256
257   foreach (ResourcePolicy::ResourceType r, optional) {
258     m_set->addResource(r);
259     ResourcePolicy::Resource *res = m_set->resource(r);
260     if (res) {
261       res->setOptional(true);
262     }
263   }
264
265   if (m_set->contains(ResourcePolicy::AudioPlaybackType)) {
266     bool isOptional = m_set->resource(ResourcePolicy::AudioPlaybackType)->isOptional();
267
268     ResourcePolicy::AudioResource *audio = new ResourcePolicy::AudioResource("camera");
269     audio->setProcessID(QCoreApplication::applicationPid());
270     audio->setOptional(isOptional);
271     m_set->addResourceObject(audio);
272   }
273
274   m_acquiring = true;
275
276   m_set->update();
277   m_set->acquire();
278
279   while (m_acquiring) {
280     QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
281   }
282
283   return m_acquired;
284 }
285
286 bool CameraResourcesWorker::release() {
287   m_acquiring = true;
288
289   m_set->release();
290
291   while (m_acquiring) {
292     QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
293   }
294
295   m_mode = CameraResources::None;
296
297   return true;
298 }
299
300 void CameraResourcesWorker::setAcquired(bool acquired) {
301   if (m_acquired != acquired) {
302     m_acquired = acquired;
303     emit acquiredChanged();
304   }
305 }
306
307 void CameraResourcesWorker::setHijacked(bool hijacked) {
308   if (m_hijacked != hijacked) {
309     m_hijacked = hijacked;
310     emit hijackedChanged();
311   }
312 }
313
314 void CameraResourcesWorker::isResourceGranted(bool *ok,
315                                               const CameraResources::ResourceType& resource) {
316
317   ResourcePolicy::ResourceType rt = (ResourcePolicy::ResourceType)resource;
318
319   ResourcePolicy::Resource *r = m_set->resource(rt);
320   if (r) {
321     *ok = r->isGranted();
322   }
323 }