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);
39 QList<QtCamGStreamerMessageHandler *> list =
40 map.values(gst_structure_get_name(s));
42 foreach (QtCamGStreamerMessageHandler *handler, list) {
43 handler->handleMessage(message);
49 void handleMessage(GstMessage *message) {
51 switch (GST_MESSAGE_TYPE(message)) {
52 case GST_MESSAGE_ELEMENT:
53 handleMessage(message, handlers);
56 case GST_MESSAGE_ERROR: {
60 gst_message_parse_error(message, &err, &debug);
62 QMetaObject::invokeMethod(q_ptr, "error", Q_ARG(QString, err->message),
63 Q_ARG(int, err->code), Q_ARG(QString, debug));
65 qDebug() << "Error" << err->message << ":" << debug;
72 case GST_MESSAGE_WARNING: {
76 gst_message_parse_warning(message, &err, &debug);
78 qDebug() << "Warning" << err->message << ":" << debug;
85 case GST_MESSAGE_INFO: {
89 gst_message_parse_info(message, &err, &debug);
91 qDebug() << "Info" << err->message << ":" << debug;
98 case GST_MESSAGE_STATE_CHANGED: {
99 if (GST_ELEMENT(GST_MESSAGE_SRC(message)) != dev->cameraBin) {
103 GstState oldState, newState, pending;
104 gst_message_parse_state_changed(message, &oldState, &newState, &pending);
105 if (oldState == GST_STATE_PAUSED && newState == GST_STATE_PLAYING) {
106 QMetaObject::invokeMethod(q_ptr, "started");
108 else if (oldState == GST_STATE_PLAYING && newState == GST_STATE_PAUSED) {
109 QMetaObject::invokeMethod(q_ptr, "stopping");
111 else if (oldState == GST_STATE_READY && newState == GST_STATE_NULL) {
112 QMetaObject::invokeMethod(q_ptr, "stopped");
123 bool handleSyncMessage(GstMessage *message) {
124 QMutexLocker locker(&syncMutex);
126 if (handleMessage(message, syncHandlers) != 0) {
133 void addHandler(QtCamGStreamerMessageHandler *handler,
134 QMultiMap<QString, QtCamGStreamerMessageHandler *>& map) {
135 if (!map.contains(handler->messageName(), handler)) {
136 map.insert(handler->messageName(), handler);
137 handler->setParent(q_ptr);
141 void removeHandler(QtCamGStreamerMessageHandler *handler,
142 QMultiMap<QString, QtCamGStreamerMessageHandler *>& map) {
143 map.remove(handler->messageName(), handler);
144 handler->setParent(0);
151 QtCamDevicePrivate *dev;
155 QtCamGStreamerMessageListener *q_ptr;
158 gboolean async_handler(GstBus *bus, GstMessage *message, gpointer data)
162 QtCamGStreamerMessageListenerPrivate *d_ptr =
163 static_cast<QtCamGStreamerMessageListenerPrivate *>(data);
165 d_ptr->handleMessage(message);
171 GstBusSyncReply sync_handler(GstBus *bus, GstMessage *message, gpointer data) {
174 QtCamGStreamerMessageListenerPrivate *d_ptr =
175 static_cast<QtCamGStreamerMessageListenerPrivate *>(data);
177 if (d_ptr->handleSyncMessage(message)) {
178 gst_message_unref(message);
185 QtCamGStreamerMessageListener::QtCamGStreamerMessageListener(GstBus *bus,
186 QtCamDevicePrivate *d,
188 QObject(parent), d_ptr(new QtCamGStreamerMessageListenerPrivate) {
194 d_ptr->watchId = gst_bus_add_watch(d_ptr->bus, async_handler, d_ptr);
196 gst_bus_set_sync_handler(d_ptr->bus, sync_handler, d_ptr);
199 QtCamGStreamerMessageListener::~QtCamGStreamerMessageListener() {
200 g_source_remove(d_ptr->watchId);
201 gst_bus_set_sync_handler(d_ptr->bus, NULL, NULL);
203 qDeleteAll(d_ptr->handlers);
205 d_ptr->syncMutex.lock();
206 qDeleteAll(d_ptr->syncHandlers);
207 d_ptr->syncMutex.unlock();
209 gst_object_unref(d_ptr->bus);
211 delete d_ptr; d_ptr = 0;
214 void QtCamGStreamerMessageListener::addHandler(QtCamGStreamerMessageHandler *handler) {
215 d_ptr->addHandler(handler, d_ptr->handlers);
218 void QtCamGStreamerMessageListener::removeHandler(QtCamGStreamerMessageHandler *handler) {
219 d_ptr->removeHandler(handler, d_ptr->handlers);
222 void QtCamGStreamerMessageListener::addSyncHandler(QtCamGStreamerMessageHandler *handler) {
223 QMutexLocker locker(&d_ptr->syncMutex);
225 d_ptr->addHandler(handler, d_ptr->syncHandlers);
228 void QtCamGStreamerMessageListener::removeSyncHandler(QtCamGStreamerMessageHandler *handler) {
229 QMutexLocker locker(&d_ptr->syncMutex);
231 d_ptr->removeHandler(handler, d_ptr->syncHandlers);
234 void QtCamGStreamerMessageListener::flushMessages() {
235 GstMessage *message = 0;
237 while ((message = gst_bus_pop(d_ptr->bus))) {
238 d_ptr->handleMessage(message);
239 gst_message_unref(message);