Reworked postcapture model
[harmattan/cameraplus] / declarative / viewfinder.cpp
1 // -*- c++ -*-
2
3 /*!
4  * This file is part of CameraPlus.
5  *
6  * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 #include "viewfinder.h"
24 #include "camera.h"
25 #include "cameraconfig.h"
26 #include "qtcamviewfinderrenderer.h"
27 #if defined(QT4)
28 #include <QDeclarativeInfo>
29 #elif defined(QT5)
30 #include <QQmlInfo>
31 #endif
32 #include <QPainter>
33 #include "qtcamdevice.h"
34 #include <QMatrix4x4>
35
36 #if defined(QT4)
37 Viewfinder::Viewfinder(QDeclarativeItem *parent) :
38   QDeclarativeItem(parent),
39 #elif defined(QT5)
40 Viewfinder::Viewfinder(QQuickItem *parent) :
41   QQuickPaintedItem(parent),
42 #endif
43   m_renderer(0),
44   m_cam(0),
45   m_conf(0),
46   m_dev(0),
47   m_enabled(true) {
48
49 #if defined(QT4)
50   setFlag(QGraphicsItem::ItemHasNoContents, false);
51 #endif
52
53 #if defined(QT5)
54   setRenderTarget(QQuickPaintedItem::FramebufferObject);
55   setSmooth(false);
56   setAntialiasing(false);
57 #endif
58 }
59
60 Viewfinder::~Viewfinder() {
61   if (m_cam) {
62     m_cam->stop(true);
63   }
64
65   if (m_dev) {
66     m_dev->setViewfinder(0);
67   }
68 }
69
70 bool Viewfinder::isRenderingEnabled() const {
71   return m_enabled;
72 }
73
74 void Viewfinder::setRenderingEnabled(bool enabled) {
75   if (m_enabled != enabled) {
76     m_enabled = enabled;
77     emit renderingEnabledChanged();
78   }
79 }
80
81 Camera *Viewfinder::camera() const {
82   return m_cam;
83 }
84
85 void Viewfinder::setCamera(Camera *camera) {
86   if (m_cam == camera) {
87     return;
88   }
89
90   if (m_cam && m_cam != camera) {
91     qmlInfo(this) << "Cannot reset Camera";
92     return;
93   }
94
95   if (!camera) {
96     qmlInfo(this) << "Camera cannot be empty";
97     return;
98   }
99
100   if (m_cam) {
101     QObject::disconnect(m_cam, SIGNAL(deviceChanged()), this, SLOT(deviceChanged()));
102     QObject::disconnect(m_cam, SIGNAL(prepareForDeviceChange()), this, SLOT(prepareForDeviceChange()));
103   }
104
105   m_cam = camera;
106
107   if (m_cam) {
108     QObject::connect(m_cam, SIGNAL(deviceChanged()), this, SLOT(deviceChanged()));
109     QObject::connect(m_cam, SIGNAL(prepareForDeviceChange()), this, SLOT(prepareForDeviceChange()));
110   }
111
112   if (isComponentComplete()) {
113     deviceChanged();
114   }
115
116   emit cameraChanged();
117 }
118
119 CameraConfig *Viewfinder::cameraConfig() const {
120   return m_conf;
121 }
122
123 void Viewfinder::setCameraConfig(CameraConfig *config) {
124   if (m_conf && m_conf != config) {
125     qmlInfo(this) << "Cannot reset CameraConfig";
126     return;
127   }
128
129   if (!config) {
130     qmlInfo(this) << "CameraConfig cannot be empty";
131     return;
132   }
133
134   if (m_conf == config) {
135     return;
136   }
137
138   m_conf = config;
139
140   if (isComponentComplete()) {
141     deviceChanged();
142   }
143
144   emit cameraConfigChanged();
145 }
146
147 #if defined(QT4)
148 void Viewfinder::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
149                        QWidget *widget) {
150
151   Q_UNUSED(widget);
152   Q_UNUSED(option);
153   painter->fillRect(boundingRect(), Qt::black);
154 #elif defined(QT5)
155 void Viewfinder::paint(QPainter *painter) {
156   painter->fillRect(contentsBoundingRect(), Qt::black);
157 #endif
158
159   if (!m_renderer || !m_enabled) {
160     return;
161   }
162
163   bool needsNativePainting = m_renderer->needsNativePainting();
164
165   if (needsNativePainting) {
166     painter->beginNativePainting();
167   }
168
169   m_renderer->paint(QMatrix4x4(painter->combinedTransform()), painter->viewport());
170
171   if (needsNativePainting) {
172     painter->endNativePainting();
173   }
174 }
175
176 QRectF Viewfinder::renderArea() const {
177   return m_renderer ? m_renderer->renderArea() : QRectF();
178 }
179
180 QSizeF Viewfinder::videoResolution() const {
181   return m_renderer ? m_renderer->videoResolution() : QSizeF();
182 }
183
184 void Viewfinder::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) {
185 #if defined(QT4)
186   QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
187 #elif defined(QT5)
188   QQuickPaintedItem::geometryChanged(newGeometry, oldGeometry);
189 #endif
190
191   if (m_renderer) {
192     m_renderer->resize(newGeometry.size());
193   }
194 }
195
196 void Viewfinder::componentComplete() {
197 #if defined(QT4)
198   QDeclarativeItem::componentComplete();
199 #elif defined(QT5)
200   QQuickPaintedItem::componentComplete();
201 #endif
202
203   if (!m_cam) {
204     qmlInfo(this) << "Camera not set";
205     return;
206   }
207
208   if (!m_conf) {
209     qmlInfo(this) << "CameraConfig not set";
210     return;
211   }
212
213   m_renderer = QtCamViewfinderRenderer::create(m_conf->config(), this);
214   if (!m_renderer) {
215     qmlInfo(this) << "Failed to create viewfinder renderer";
216     return;
217   }
218
219   m_renderer->resize(QSizeF(width(), height()));
220   QObject::connect(m_renderer, SIGNAL(updateRequested()), this, SLOT(updateRequested()));
221   QObject::connect(m_renderer, SIGNAL(renderAreaChanged()), this, SIGNAL(renderAreaChanged()));
222   QObject::connect(m_renderer, SIGNAL(videoResolutionChanged()), this, SIGNAL(videoResolutionChanged()));
223 }
224
225 void Viewfinder::deviceChanged() {
226   if (!m_renderer) {
227     qmlInfo(this) << "No renderer";
228     return;
229   }
230
231   if (m_dev) {
232     qmlInfo(this) << "Cannot set a new device without cleaning up the existing one";
233     abort();
234   }
235
236   m_dev = m_cam->device();
237
238   if (m_dev) {
239     m_dev->setViewfinder(this);
240   }
241
242   emit renderAreaChanged();
243   emit videoResolutionChanged();
244 }
245
246 GstElement *Viewfinder::sinkElement() {
247   return m_renderer ? m_renderer->sinkElement() : 0;
248 }
249
250 void Viewfinder::stop() {
251   if (m_renderer) {
252     m_renderer->reset();
253   }
254 }
255
256 void Viewfinder::updateRequested() {
257   if (m_enabled) {
258     update();
259   }
260 }
261
262 void Viewfinder::prepareForDeviceChange() {
263   if (m_dev) {
264     m_dev->setViewfinder(0);
265     m_dev = 0;
266   }
267 }