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 // If we have a temp file then we rename it:
95 if (!mode->tempFileName.isEmpty() && !mode->fileName.isEmpty()) {
96 if (!QFile::rename(mode->tempFileName, mode->fileName)) {
97 qCritical() << "Failed to rename" << mode->tempFileName << "to" << mode->fileName;
102 const GstStructure *s = gst_message_get_structure(message);
103 if (gst_structure_has_field(s, "filename")) {
104 const char *str = gst_structure_get_string(s, "filename");
106 fileName = QString::fromUtf8(str);
110 if (fileName.isEmpty()) {
111 fileName = mode->fileName;
114 QMetaObject::invokeMethod(mode->q_ptr, "saved", Q_ARG(QString, fileName));
117 QtCamModePrivate *mode;
120 QtCamMode::QtCamMode(QtCamModePrivate *d, const char *mode, const char *done, QObject *parent) :
121 QObject(parent), d_ptr(d) {
124 d_ptr->id = d_ptr->modeId(mode);
125 d_ptr->previewImageHandler = new PreviewImageHandler(this, this);
126 d_ptr->doneHandler = new DoneHandler(d_ptr, done, this);
129 QtCamMode::~QtCamMode() {
130 delete d_ptr; d_ptr = 0;
133 void QtCamMode::activate() {
134 if (!d_ptr->dev->cameraBin) {
138 if (d_ptr->dev->active == this) {
142 if (d_ptr->dev->active) {
143 d_ptr->dev->active->deactivate();
146 d_ptr->dev->active = this;
148 // TODO: check that we can actually do it. Perhaps the pipeline is busy.
149 g_object_set(d_ptr->dev->cameraBin, "mode", d_ptr->id, NULL);
151 d_ptr->dev->listener->addHandler(d_ptr->previewImageHandler);
152 d_ptr->dev->listener->addHandler(d_ptr->doneHandler);
158 QMetaObject::invokeMethod(d_ptr->dev->q_ptr, "modeChanged");
160 emit activeChanged();
163 void QtCamMode::deactivate() {
164 if (d_ptr->dev->active != this) {
168 d_ptr->dev->listener->removeHandler(d_ptr->previewImageHandler);
169 d_ptr->dev->listener->removeHandler(d_ptr->doneHandler);
171 d_ptr->previewImageHandler->setParent(this);
172 d_ptr->doneHandler->setParent(this);
176 d_ptr->dev->active = 0;
178 QMetaObject::invokeMethod(d_ptr->dev->q_ptr, "modeChanged");
180 emit activeChanged();
183 bool QtCamMode::canCapture() {
184 return d_ptr->dev->cameraBin && isActive() && d_ptr->dev->q_ptr->isRunning() &&
188 bool QtCamMode::isActive() {
189 return d_ptr->dev->active == this;
192 QtCamDevice *QtCamMode::device() const {
193 return d_ptr->dev->q_ptr;