Cleaned up some commented out defines
[harmattan/cameraplus] / lib / qtcammode.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 "qtcammode.h"
22 #include "qtcammode_p.h"
23 #include "qtcamdevice_p.h"
24 #include "qtcamdevice.h"
25 #include <QDebug>
26 #include "qtcamgstreamermessagehandler.h"
27 #include "qtcamgstreamermessagelistener.h"
28 #include <gst/video/video.h>
29 #include <QImage>
30 #include <QFile>
31
32 class PreviewImageHandler : public QtCamGStreamerMessageHandler {
33 public:
34   PreviewImageHandler(QtCamMode *m, QObject *parent = 0) :
35     QtCamGStreamerMessageHandler("preview-image", parent) {
36     mode = m;
37   }
38
39   virtual void handleMessage(GstMessage *message) {
40     const GstStructure *s = gst_message_get_structure(message);
41     if (!s) {
42       return;
43     }
44
45     const char *file = gst_structure_get_string(s, "location");
46     if (!file) {
47       return;
48     }
49
50     const GValue *val = gst_structure_get_value(s, "buffer");
51     if (!val) {
52       return;
53     }
54
55     GstBuffer *buffer = gst_value_get_buffer(val);
56     if (!buffer) {
57       return;
58     }
59
60     int width, height;
61     GstVideoFormat fmt;
62     if (!gst_video_format_parse_caps(buffer->caps, &fmt, &width, &height)) {
63       return;
64     }
65
66     if (fmt !=  GST_VIDEO_FORMAT_BGRx || width <= 0 || height <= 0) {
67       return;
68     }
69
70     QImage image(buffer->data, width, height, QImage::Format_RGB32);
71
72     // We need to copy because GStreamer will free the buffer after we return
73     // and since QImage doesn't copythe data by default we will end up with garbage.
74     // There is no way to subclass QImage to prevent copying :|
75     QImage cp = image.copy();
76
77     QString fileName = QString::fromUtf8(file);
78
79     QMetaObject::invokeMethod(mode, "previewAvailable",
80                               Q_ARG(QImage, cp), Q_ARG(QString, fileName));
81   }
82
83   QtCamMode *mode;
84 };
85
86 class DoneHandler : public QtCamGStreamerMessageHandler {
87 public:
88   DoneHandler(QtCamModePrivate *m, const char *done, QObject *parent = 0) :
89     QtCamGStreamerMessageHandler(done, parent) {
90     mode = m;
91   }
92
93   virtual void handleMessage(GstMessage *message) {
94     const GstStructure *s = gst_message_get_structure(message);
95     if (gst_structure_has_field(s, "filename")) {
96       const char *str = gst_structure_get_string(s, "filename");
97       if (str) {
98         mode->tempFileName = QString::fromUtf8(str);
99       }
100     }
101
102     if (mode->fileName.isEmpty()) {
103       mode->fileName = mode->tempFileName;
104     }
105
106     if (!mode->tempFileName.isEmpty() && !mode->fileName.isEmpty() &&
107         mode->tempFileName != mode->fileName) {
108       if (!QFile::rename(mode->tempFileName, mode->fileName)) {
109         qCritical() << "Failed to rename" << mode->tempFileName << "to" << mode->fileName;
110       }
111     }
112
113     QMetaObject::invokeMethod(mode->q_ptr, "saved", Q_ARG(QString, mode->fileName));
114   }
115
116   QtCamModePrivate *mode;
117 };
118
119 QtCamMode::QtCamMode(QtCamModePrivate *d, const char *mode, const char *done, QObject *parent) :
120   QObject(parent), d_ptr(d) {
121
122   d_ptr->q_ptr = this;
123   d_ptr->id = d_ptr->modeId(mode);
124   d_ptr->previewImageHandler = new PreviewImageHandler(this, this);
125   d_ptr->doneHandler = new DoneHandler(d_ptr, done, this);
126 }
127
128 QtCamMode::~QtCamMode() {
129   delete d_ptr; d_ptr = 0;
130 }
131
132 void QtCamMode::activate() {
133   if (!d_ptr->dev->cameraBin) {
134     return;
135   }
136
137   if (d_ptr->dev->active == this) {
138     return;
139   }
140
141   if (d_ptr->dev->active) {
142     d_ptr->dev->active->deactivate();
143   }
144
145   d_ptr->dev->active = this;
146
147   // TODO: check that we can actually do it. Perhaps the pipeline is busy.
148   g_object_set(d_ptr->dev->cameraBin, "mode", d_ptr->id, NULL);
149
150   d_ptr->dev->listener->addHandler(d_ptr->previewImageHandler);
151   d_ptr->dev->listener->addHandler(d_ptr->doneHandler);
152
153   start();
154
155   applySettings();
156
157   QMetaObject::invokeMethod(d_ptr->dev->q_ptr, "modeChanged");
158
159   emit activeChanged();
160 }
161
162 void QtCamMode::deactivate() {
163   if (d_ptr->dev->active != this) {
164     return;
165   }
166
167   d_ptr->dev->listener->removeHandler(d_ptr->previewImageHandler);
168   d_ptr->dev->listener->removeHandler(d_ptr->doneHandler);
169
170   d_ptr->previewImageHandler->setParent(this);
171   d_ptr->doneHandler->setParent(this);
172
173   stop();
174
175   d_ptr->dev->active = 0;
176
177   QMetaObject::invokeMethod(d_ptr->dev->q_ptr, "modeChanged");
178
179   emit activeChanged();
180 }
181
182 bool QtCamMode::canCapture() {
183   return d_ptr->dev->cameraBin && isActive() && d_ptr->dev->q_ptr->isRunning() &&
184     !d_ptr->dev->error;
185 }
186
187 bool QtCamMode::isActive() {
188   return d_ptr->dev->active == this;
189 }
190
191 QtCamDevice *QtCamMode::device() const {
192   return d_ptr->dev->q_ptr;
193 }