2 * This file is part of CameraPlus.
4 * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
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.
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.
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
21 #include "qtcammode.h"
22 #include "qtcammode_p.h"
23 #include "qtcamdevice_p.h"
24 #include "qtcamdevice.h"
26 #include "qtcamgstreamermessagehandler.h"
27 #include "qtcamgstreamermessagelistener.h"
28 #include <gst/video/video.h>
32 class PreviewImageHandler : public QtCamGStreamerMessageHandler {
34 PreviewImageHandler(QtCamMode *m, QObject *parent = 0) :
35 QtCamGStreamerMessageHandler("preview-image", parent) {
39 virtual void handleMessage(GstMessage *message) {
40 const GstStructure *s = gst_message_get_structure(message);
45 const char *file = gst_structure_get_string(s, "location");
50 const GValue *val = gst_structure_get_value(s, "buffer");
55 GstBuffer *buffer = gst_value_get_buffer(val);
62 if (!gst_video_format_parse_caps(buffer->caps, &fmt, &width, &height)) {
66 if (fmt != GST_VIDEO_FORMAT_BGRx || width <= 0 || height <= 0) {
70 QImage image(buffer->data, width, height, QImage::Format_RGB32);
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();
77 QString fileName = QString::fromUtf8(file);
79 QMetaObject::invokeMethod(mode, "previewAvailable",
80 Q_ARG(QImage, cp), Q_ARG(QString, fileName));
86 class DoneHandler : public QtCamGStreamerMessageHandler {
88 DoneHandler(QtCamModePrivate *m, const char *done, QObject *parent = 0) :
89 QtCamGStreamerMessageHandler(done, parent) {
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");
98 mode->tempFileName = QString::fromUtf8(str);
102 if (mode->fileName.isEmpty()) {
103 mode->fileName = mode->tempFileName;
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;
113 QMetaObject::invokeMethod(mode->q_ptr, "saved", Q_ARG(QString, mode->fileName));
116 QtCamModePrivate *mode;
119 QtCamMode::QtCamMode(QtCamModePrivate *d, const char *mode, const char *done, QObject *parent) :
120 QObject(parent), d_ptr(d) {
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);
128 QtCamMode::~QtCamMode() {
129 delete d_ptr; d_ptr = 0;
132 void QtCamMode::activate() {
133 if (!d_ptr->dev->cameraBin) {
137 if (d_ptr->dev->active == this) {
141 if (d_ptr->dev->active) {
142 d_ptr->dev->active->deactivate();
145 d_ptr->dev->active = this;
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);
150 d_ptr->dev->listener->addHandler(d_ptr->previewImageHandler);
151 d_ptr->dev->listener->addHandler(d_ptr->doneHandler);
157 QMetaObject::invokeMethod(d_ptr->dev->q_ptr, "modeChanged");
159 emit activeChanged();
162 void QtCamMode::deactivate() {
163 if (d_ptr->dev->active != this) {
167 d_ptr->dev->listener->removeHandler(d_ptr->previewImageHandler);
168 d_ptr->dev->listener->removeHandler(d_ptr->doneHandler);
170 d_ptr->previewImageHandler->setParent(this);
171 d_ptr->doneHandler->setParent(this);
175 d_ptr->dev->active = 0;
177 QMetaObject::invokeMethod(d_ptr->dev->q_ptr, "modeChanged");
179 emit activeChanged();
182 bool QtCamMode::canCapture() {
183 return d_ptr->dev->cameraBin && isActive() && d_ptr->dev->q_ptr->isRunning() &&
187 bool QtCamMode::isActive() {
188 return d_ptr->dev->active == this;
191 QtCamDevice *QtCamMode::device() const {
192 return d_ptr->dev->q_ptr;