Fixes for changing video resolution between 16:9 and 4:3
[harmattan/cameraplus] / declarative / mode.cpp
1 /*!
2  * This file is part of CameraPlus.
3  *
4  * Copyright (C) 2012-2013 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 "mode.h"
22 #include "qtcammode.h"
23 #include "camera.h"
24 #include "qtcamdevice.h"
25 #include "previewprovider.h"
26
27 Mode::Mode(QObject *parent) :
28   QObject(parent),
29   m_cam(0),
30   m_mode(0),
31   m_seq(0),
32   m_previewEnabled(true) {
33
34 }
35
36 Mode::~Mode() {
37   m_cam = 0;
38   m_mode = 0;
39 }
40
41 Camera *Mode::camera() {
42   return m_cam;
43 }
44
45 void Mode::setCamera(Camera *camera) {
46   if (camera == m_cam) {
47     return;
48   }
49
50   if (m_cam) {
51     QObject::disconnect(m_cam, SIGNAL(prepareForDeviceChange()), this, SLOT(prepareForDeviceChange()));
52     QObject::disconnect(m_cam, SIGNAL(deviceChanged()), this, SLOT(deviceChanged()));
53     QObject::disconnect(m_cam, SIGNAL(deviceChanged()), this, SIGNAL(isReadyChanged()));
54   }
55
56   m_cam = camera;
57
58   if (m_cam) {
59     QObject::connect(m_cam, SIGNAL(prepareForDeviceChange()), this, SLOT(prepareForDeviceChange()));
60     QObject::connect(m_cam, SIGNAL(deviceChanged()), this, SLOT(deviceChanged()));
61     QObject::connect(m_cam, SIGNAL(deviceChanged()), this, SIGNAL(isReadyChanged()));
62   }
63
64   emit cameraChanged();
65
66   deviceChanged();
67
68   emit isReadyChanged();
69 }
70
71 bool Mode::isActive() {
72   return m_mode ? m_mode->isActive() : false;
73 }
74
75 bool Mode::canCapture() {
76   return m_mode ? m_mode->canCapture() : false;
77 }
78
79 void Mode::deviceChanged() {
80   if (!m_cam || !m_cam->device()) {
81     return;
82   }
83
84   changeMode();
85
86   if (m_mode) {
87     QObject::connect(m_mode, SIGNAL(canCaptureChanged()), this, SIGNAL(canCaptureChanged()));
88     QObject::connect(m_mode, SIGNAL(saved(const QString&)), this, SIGNAL(saved(const QString&)));
89     QObject::connect(m_mode, SIGNAL(previewAvailable(const QImage&, const QString&)),
90                      this, SLOT(gotPreview(const QImage&, const QString&)));
91     QObject::connect(m_mode, SIGNAL(activeChanged()), this, SIGNAL(activeChanged()));
92     QObject::connect(m_mode, SIGNAL(activeChanged()), this, SIGNAL(canCaptureChanged()));
93     QObject::connect(m_cam->device(), SIGNAL(idleStateChanged(bool)),
94                      this, SIGNAL(canCaptureChanged()));
95     QObject::connect(m_cam->device(), SIGNAL(runningStateChanged(bool)),
96                      this, SIGNAL(canCaptureChanged()));
97
98     setPreviewState();
99
100     postChangeMode();
101   }
102
103   emit canCaptureChanged();
104   emit activeChanged();
105 }
106
107 void Mode::gotPreview(const QImage& image, const QString& fileName) {
108   PreviewProvider::instance()->setPreview(image);
109
110   // HACK: QML insists on caching the images.
111   QString url = QString("image://preview/%1").arg(m_seq);
112   ++m_seq;
113
114   emit previewAvailable(url, fileName);
115 }
116
117 bool Mode::isReady() const {
118   return m_mode;
119 }
120
121 void Mode::prepareForDeviceChange() {
122   if (m_mode) {
123     QObject::disconnect(m_mode, SIGNAL(canCaptureChanged()), this, SIGNAL(canCaptureChanged()));
124     QObject::disconnect(m_mode, SIGNAL(saved(const QString&)),
125                         this, SIGNAL(saved(const QString&)));
126     QObject::disconnect(m_mode, SIGNAL(previewAvailable(const QImage&, const QString&)),
127                         this, SLOT(gotPreview(const QImage&, const QString&)));
128     QObject::disconnect(m_mode, SIGNAL(activeChanged()), this, SIGNAL(activeChanged()));
129     QObject::disconnect(m_mode, SIGNAL(activeChanged()), this, SIGNAL(canCaptureChanged()));
130     QObject::disconnect(m_cam->device(), SIGNAL(idleStateChanged(bool)),
131                         this, SIGNAL(canCaptureChanged()));
132     QObject::disconnect(m_cam->device(), SIGNAL(runningStateChanged(bool)),
133                         this, SIGNAL(canCaptureChanged()));
134
135     preChangeMode();
136   }
137 }
138
139 bool Mode::isPreviewEnabled() {
140   return m_previewEnabled;
141 }
142
143 void Mode::setPreviewEnabled(bool enabled) {
144   if (enabled != m_previewEnabled) {
145     m_previewEnabled = enabled;
146
147     if (m_mode) {
148       setPreviewState();
149     }
150
151     emit enablePreviewChanged();
152   }
153 }
154
155 void Mode::setPreviewState() {
156   if (m_previewEnabled) {
157     m_mode->enablePreview();
158   }
159   else {
160     m_mode->disablePreview();
161   }
162 }