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 "qtcamgstreamermessagelistener.h"
22 #include "qtcamgstreamermessagehandler.h"
26 #include "qtcamdevice_p.h"
28 class QtCamGStreamerMessageListenerPrivate {
30 QMultiMap<QString, QtCamGStreamerMessageHandler *> handlers;
31 QMultiMap<QString, QtCamGStreamerMessageHandler *> syncHandlers;
33 int handleMessage(GstMessage *message, QMultiMap<QString, QtCamGStreamerMessageHandler *>& map) {
34 const GstStructure *s = gst_message_get_structure(message);
40 qDebug() << "Message" << gst_structure_get_name(s);
43 QList<QtCamGStreamerMessageHandler *> list = map.values(gst_structure_get_name(s));
45 foreach (QtCamGStreamerMessageHandler *handler, list) {
46 handler->handleMessage(message);
52 void handleMessage(GstMessage *message) {
54 switch (GST_MESSAGE_TYPE(message)) {
55 case GST_MESSAGE_ELEMENT:
56 handleMessage(message, handlers);
59 case GST_MESSAGE_ERROR: {
63 gst_message_parse_error(message, &err, &debug);
65 QMetaObject::invokeMethod(q_ptr, "error", Q_ARG(QString, err->message),
66 Q_ARG(int, err->code), Q_ARG(QString, debug));
69 qDebug() << "Error" << err->message << ":" << debug;
77 case GST_MESSAGE_WARNING: {
81 gst_message_parse_warning(message, &err, &debug);
83 qDebug() << "Warning" << err->message << ":" << debug;
90 case GST_MESSAGE_INFO: {
94 gst_message_parse_info(message, &err, &debug);
96 qDebug() << "Info" << err->message << ":" << debug;
103 case GST_MESSAGE_STATE_CHANGED: {
104 if (GST_ELEMENT(GST_MESSAGE_SRC(message)) != dev->cameraBin) {
108 GstState oldState, newState, pending;
109 gst_message_parse_state_changed(message, &oldState, &newState, &pending);
110 if (oldState == GST_STATE_PAUSED && newState == GST_STATE_PLAYING) {
111 QMetaObject::invokeMethod(q_ptr, "started");
113 else if (oldState == GST_STATE_PLAYING && newState == GST_STATE_PAUSED) {
114 QMetaObject::invokeMethod(q_ptr, "stopping");
116 else if (oldState == GST_STATE_READY && newState == GST_STATE_NULL) {
117 QMetaObject::invokeMethod(q_ptr, "stopped");
127 bool handleSyncMessage(GstMessage *message) {
128 QMutexLocker locker(&syncMutex);
130 if (handleMessage(message, syncHandlers) != 0) {
137 void addHandler(QtCamGStreamerMessageHandler *handler,
138 QMultiMap<QString, QtCamGStreamerMessageHandler *>& map) {
139 if (!map.contains(handler->messageName(), handler)) {
140 map.insert(handler->messageName(), handler);
141 handler->setParent(q_ptr);
145 void removeHandler(QtCamGStreamerMessageHandler *handler,
146 QMultiMap<QString, QtCamGStreamerMessageHandler *>& map) {
147 map.remove(handler->messageName(), handler);
148 handler->setParent(0);
155 QtCamDevicePrivate *dev;
159 QtCamGStreamerMessageListener *q_ptr;
162 gboolean async_handler(GstBus *bus, GstMessage *message, gpointer data)
166 QtCamGStreamerMessageListenerPrivate *d_ptr =
167 static_cast<QtCamGStreamerMessageListenerPrivate *>(data);
169 d_ptr->handleMessage(message);
175 GstBusSyncReply sync_handler(GstBus *bus, GstMessage *message, gpointer data) {
178 QtCamGStreamerMessageListenerPrivate *d_ptr =
179 static_cast<QtCamGStreamerMessageListenerPrivate *>(data);
181 if (d_ptr->handleSyncMessage(message)) {
182 // We need to pass the message.
183 // Issue is we have 2 video-done handlers, a sync and an async.
184 // If we drop the message then the async handler will never see it :|
191 QtCamGStreamerMessageListener::QtCamGStreamerMessageListener(GstBus *bus,
192 QtCamDevicePrivate *d,
194 QObject(parent), d_ptr(new QtCamGStreamerMessageListenerPrivate) {
200 d_ptr->watchId = gst_bus_add_watch(d_ptr->bus, async_handler, d_ptr);
202 gst_bus_set_sync_handler(d_ptr->bus, sync_handler, d_ptr);
205 QtCamGStreamerMessageListener::~QtCamGStreamerMessageListener() {
206 g_source_remove(d_ptr->watchId);
207 gst_bus_set_sync_handler(d_ptr->bus, NULL, NULL);
209 qDeleteAll(d_ptr->handlers);
211 d_ptr->syncMutex.lock();
212 qDeleteAll(d_ptr->syncHandlers);
213 d_ptr->syncMutex.unlock();
215 gst_object_unref(d_ptr->bus);
217 delete d_ptr; d_ptr = 0;
220 void QtCamGStreamerMessageListener::addHandler(QtCamGStreamerMessageHandler *handler) {
221 d_ptr->addHandler(handler, d_ptr->handlers);
224 void QtCamGStreamerMessageListener::removeHandler(QtCamGStreamerMessageHandler *handler) {
225 d_ptr->removeHandler(handler, d_ptr->handlers);
228 void QtCamGStreamerMessageListener::addSyncHandler(QtCamGStreamerMessageHandler *handler) {
229 QMutexLocker locker(&d_ptr->syncMutex);
231 d_ptr->addHandler(handler, d_ptr->syncHandlers);
234 void QtCamGStreamerMessageListener::removeSyncHandler(QtCamGStreamerMessageHandler *handler) {
235 QMutexLocker locker(&d_ptr->syncMutex);
237 d_ptr->removeHandler(handler, d_ptr->syncHandlers);
240 void QtCamGStreamerMessageListener::flushMessages() {
241 GstMessage *message = 0;
243 while ((message = gst_bus_pop(d_ptr->bus))) {
244 d_ptr->handleMessage(message);
245 gst_message_unref(message);