Don't ignore errors while stopping the pipeline.
[harmattan/cameraplus] / lib / qtcamdevice_p.h
1 // -*- c++ -*-
2
3 /*!
4  * This file is part of CameraPlus.
5  *
6  * Copyright (C) 2012 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 #ifndef QT_CAM_DEVICE_P_H
24 #define QT_CAM_DEVICE_P_H
25
26 #include <QDebug>
27 #include <gst/gst.h>
28 #include "qtcamconfig.h"
29 #include "qtcamviewfinder.h"
30 #include "qtcamdevice.h"
31 #include "qtcammode.h"
32
33 class QtCamGStreamerMessageListener;
34 class QtCamMode;
35 class QtCamImageMode;
36 class QtCamVideoMode;
37
38 class QtCamDevicePrivate {
39 public:
40   QtCamDevicePrivate() :
41     cameraBin(0),
42     videoSource(0),
43     wrapperVideoSource(0),
44     image(0),
45     video(0),
46     active(0),
47     viewfinder(0),
48     conf(0),
49     error(false),
50     notifications(0) {
51
52   }
53
54   GstElement *createAndAddElement(const QString& elementName, const char *prop, const char *name) {
55     GstElement *elem = gst_element_factory_make(elementName.toAscii(), name);
56     if (!elem) {
57       qWarning() << "Failed to create" << elementName;
58       return 0;
59     }
60
61     g_object_set(cameraBin, prop, elem, NULL);
62
63     return elem;
64   }
65
66   void createAndAddVideoSource() {
67     // TODO: rework this function
68     GstElement *src, *wrapper;
69     QString wrapperSrc = conf->wrapperVideoSource();
70     QString prop = conf->wrapperVideoSourceProperty();
71
72     if (!prop.isEmpty() && !wrapperSrc.isEmpty()) {
73       wrapper = gst_element_factory_make(wrapperSrc.toAscii(), "QCameraWrapperVideoSrc");
74       if (!wrapper) {
75         qCritical() << "Failed to create wrapper source" << wrapperSrc;
76         return;
77       }
78     }
79
80     src = gst_element_factory_make(conf->videoSource().toAscii(),
81                                                "QtCameraVideoSrc");
82     if (!src) {
83       qCritical() << "Failed to create video source";
84       if (wrapper) {
85         gst_object_unref(wrapper);
86       }
87       return;
88     }
89
90     if (wrapper) {
91       g_object_set(wrapper, prop.toAscii(), src, NULL);
92       g_object_set(cameraBin, "camera-source", wrapper, NULL);
93     }
94
95     videoSource = src;
96     wrapperVideoSource = wrapper;
97
98     if (!id.isValid() || id.isNull()) {
99       return;
100     }
101
102     if (conf->deviceScannerType() == SCANNER_TYPE_ENUM) {
103       int dev = id.toInt();
104       g_object_set(src, conf->deviceScannerProperty().toAscii().data(), dev, NULL);
105     }
106     else {
107       QString dev = id.toString();
108       g_object_set(src, conf->deviceScannerProperty().toAscii().data(),
109                    dev.toAscii().data(), NULL);
110     }
111   }
112
113   bool setViewfinderSink() {
114     GstElement *sink;
115     g_object_get(cameraBin, "viewfinder-sink", &sink, NULL);
116
117     if (sink) {
118       gst_object_unref(sink);
119       return true;
120     }
121
122     sink = viewfinder->sinkElement();
123     if (!sink) {
124       qCritical() << "Failed to create GStreamer sink element";
125       return false;
126     }
127
128     g_object_set(cameraBin, "viewfinder-sink", sink, NULL);
129
130     return true;
131   }
132
133   void _d_error(const QString& message, int code, const QString& debug) {
134     error = true;
135
136     QMetaObject::invokeMethod(q_ptr, "error", Q_ARG(QString, message),
137                               Q_ARG(int, code), Q_ARG(QString, debug));
138
139     if (active) {
140       QMetaObject::invokeMethod(active, "canCaptureChanged", Qt::QueuedConnection);
141     }
142   }
143
144   void _d_stopped() {
145     QMetaObject::invokeMethod(q_ptr, "stopped");
146   }
147
148   void _d_stopping() {
149     if (active) {
150       QMetaObject::invokeMethod(active, "canCaptureChanged", Qt::QueuedConnection);
151     }
152
153     QMetaObject::invokeMethod(q_ptr, "stopping", Qt::QueuedConnection);
154     QMetaObject::invokeMethod(q_ptr, "runningStateChanged", Qt::QueuedConnection,
155                               Q_ARG(bool, false));
156   }
157
158   void _d_started() {
159     if (active) {
160       QMetaObject::invokeMethod(active, "canCaptureChanged", Qt::QueuedConnection);
161     }
162
163     QMetaObject::invokeMethod(q_ptr, "started", Qt::QueuedConnection);
164     QMetaObject::invokeMethod(q_ptr, "runningStateChanged", Qt::QueuedConnection,
165                               Q_ARG(bool, true));
166   }
167
168   void setAudioCaptureCaps() {
169     QString captureCaps = conf->audioCaptureCaps();
170     if (!captureCaps.isEmpty()) {
171       GstCaps *caps = gst_caps_from_string(captureCaps.toAscii().data());
172       if (caps) {
173         g_object_set(cameraBin, "audio-capture-caps", caps, NULL);
174         gst_caps_unref(caps);
175       }
176     }
177   }
178
179   bool isWrapperReady() {
180     if (!wrapperVideoSource) {
181       return false;
182     }
183
184     gboolean ready = FALSE;
185     g_object_get(wrapperVideoSource, "ready-for-capture", &ready, NULL);
186
187     return ready == TRUE;
188   }
189
190   static void on_ready_for_capture_changed(GObject *obj, GParamSpec *pspec,
191                                            QtCamDevicePrivate *d)  {
192     Q_UNUSED(obj);
193     Q_UNUSED(pspec);
194
195     if (!d->active) {
196       return;
197     }
198
199     QMetaObject::invokeMethod(d->active, "canCaptureChanged", Qt::QueuedConnection);
200   }
201
202   static void on_idle_changed(GObject *obj, GParamSpec *pspec, QtCamDevicePrivate *d) {
203     Q_UNUSED(obj);
204     Q_UNUSED(pspec);
205
206     QMetaObject::invokeMethod(d->q_ptr, "idleStateChanged", Qt::QueuedConnection,
207                               Q_ARG(bool, d->q_ptr->isIdle()));
208   }
209
210 #if 0
211   void resetCapabilities() {
212     g_object_set(cameraBin, "zoom", 1.0, NULL);
213     g_object_set(videoSource, "flash-mode", 0, NULL);
214
215     // TODO: should scene mode be manual or automatic ?
216     g_object_set(videoSource, "scene-mode", 0, NULL);
217   }
218 #endif
219
220   QString name;
221   QVariant id;
222
223   QtCamDevice *q_ptr;
224
225   GstElement *cameraBin;
226   GstElement *videoSource;
227   GstElement *wrapperVideoSource;
228
229   QtCamImageMode *image;
230   QtCamVideoMode *video;
231   QtCamMode *active;
232
233   QtCamViewfinder *viewfinder;
234   QtCamConfig *conf;
235   QtCamGStreamerMessageListener *listener;
236   bool error;
237   QtCamNotifications *notifications;
238 };
239
240 #endif /* QT_CAM_DEVICE_P_H */