94600e140e6287e6bd33020eaf616717514d503e
[harmattan/cameraplus] / lib / qtcamgstreamermessagelistener.cpp
1 #include "qtcamgstreamermessagelistener.h"
2 #include "qtcamgstreamermessagehandler.h"
3 #include <QMultiMap>
4 #include <QMutex>
5 #include <QDebug>
6 #include "qtcamdevice_p.h"
7
8 class QtCamGStreamerMessageListenerPrivate {
9 public:
10   QMultiMap<QString, QtCamGStreamerMessageHandler *> handlers;
11   QMultiMap<QString, QtCamGStreamerMessageHandler *> syncHandlers;
12
13   int handleMessage(GstMessage *message, QMultiMap<QString, QtCamGStreamerMessageHandler *>& map) {
14     const GstStructure *s = gst_message_get_structure(message);
15     if (!s) {
16       return 0;
17     }
18
19     QList<QtCamGStreamerMessageHandler *> list =
20       map.values(gst_structure_get_name(s));
21
22     foreach (QtCamGStreamerMessageHandler *handler, list) {
23       handler->handleMessage(message);
24     }
25
26     return list.size();
27   }
28
29   void handleMessage(GstMessage *message) {
30
31     switch (GST_MESSAGE_TYPE(message)) {
32     case GST_MESSAGE_ELEMENT:
33       handleMessage(message, handlers);
34       break;
35
36     case GST_MESSAGE_ERROR: {
37       GError *err = NULL;
38       gchar *debug;
39
40       gst_message_parse_error(message, &err, &debug);
41
42       QMetaObject::invokeMethod(q_ptr, "error", Q_ARG(QString, err->message),
43                                 Q_ARG(int, err->code), Q_ARG(QString, debug));
44
45       qDebug() << "Error" << err->message << ":" << debug;
46
47       g_error_free(err);
48       g_free(debug);
49     }
50       break;
51
52     case GST_MESSAGE_WARNING: {
53       GError *err = NULL;
54       gchar *debug;
55
56       gst_message_parse_warning(message, &err, &debug);
57
58       qDebug() << "Warning" << err->message << ":" << debug;
59
60       g_error_free(err);
61       g_free(debug);
62     }
63       break;
64
65     case GST_MESSAGE_INFO: {
66       GError *err = NULL;
67       gchar *debug;
68
69       gst_message_parse_info(message, &err, &debug);
70
71       qDebug() << "Info" << err->message << ":" << debug;
72
73       g_error_free(err);
74       g_free(debug);
75     }
76       break;
77
78     case GST_MESSAGE_STATE_CHANGED: {
79       if (GST_ELEMENT(GST_MESSAGE_SRC(message)) != dev->cameraBin) {
80         break;
81       }
82
83       GstState oldState, newState, pending;
84       gst_message_parse_state_changed(message, &oldState, &newState, &pending);
85       if (oldState == GST_STATE_PAUSED && newState == GST_STATE_PLAYING) {
86         QMetaObject::invokeMethod(q_ptr, "started");
87       }
88       else if (oldState == GST_STATE_PLAYING && newState == GST_STATE_PAUSED) {
89         QMetaObject::invokeMethod(q_ptr, "stopped");
90       }
91     }
92       break;
93
94     default:
95       // TODO: other types
96       break;
97     }
98   }
99
100   bool handleSyncMessage(GstMessage *message) {
101     QMutexLocker locker(&syncMutex);
102
103     if (handleMessage(message, syncHandlers) != 0) {
104       return true;
105     }
106
107     return false;
108   }
109
110   void addHandler(QtCamGStreamerMessageHandler *handler,
111                   QMultiMap<QString, QtCamGStreamerMessageHandler *>& map) {
112     if (!map.contains(handler->messageName(), handler)) {
113       map.insert(handler->messageName(), handler);
114       handler->setParent(q_ptr);
115     }
116   }
117
118   void removeHandler(QtCamGStreamerMessageHandler *handler,
119                      QMultiMap<QString, QtCamGStreamerMessageHandler *>& map) {
120     map.remove(handler->messageName(), handler);
121     handler->setParent(0);
122   }
123
124   QMutex syncMutex;
125
126   GstBus *bus;
127
128   QtCamDevicePrivate *dev;
129
130   guint watchId;
131
132   QtCamGStreamerMessageListener *q_ptr;
133 };
134
135 gboolean async_handler(GstBus *bus, GstMessage *message, gpointer data)
136 {
137   Q_UNUSED(bus);
138
139   QtCamGStreamerMessageListenerPrivate *d_ptr =
140     static_cast<QtCamGStreamerMessageListenerPrivate *>(data);
141
142   d_ptr->handleMessage(message);
143
144   // Call us again
145   return TRUE;
146 }
147
148 GstBusSyncReply sync_handler(GstBus *bus, GstMessage *message, gpointer data) {
149   Q_UNUSED(bus);
150
151   QtCamGStreamerMessageListenerPrivate *d_ptr =
152     static_cast<QtCamGStreamerMessageListenerPrivate *>(data);
153
154   if (d_ptr->handleSyncMessage(message)) {
155     gst_message_unref(message);
156     return GST_BUS_DROP;
157   }
158
159   return GST_BUS_PASS;
160 }
161
162 QtCamGStreamerMessageListener::QtCamGStreamerMessageListener(GstBus *bus,
163                                                              QtCamDevicePrivate *d,
164                                                              QObject *parent) :
165   QObject(parent), d_ptr(new QtCamGStreamerMessageListenerPrivate) {
166
167   d_ptr->dev = d;
168   d_ptr->bus = bus;
169   d_ptr->q_ptr = this;
170
171   d_ptr->watchId = gst_bus_add_watch(d_ptr->bus, async_handler, d_ptr);
172
173   gst_bus_set_sync_handler(d_ptr->bus, sync_handler, d_ptr);
174 }
175
176 QtCamGStreamerMessageListener::~QtCamGStreamerMessageListener() {
177   g_source_remove(d_ptr->watchId);
178   gst_bus_set_sync_handler(d_ptr->bus, NULL, NULL);
179
180   qDeleteAll(d_ptr->handlers);
181
182   d_ptr->syncMutex.lock();
183   qDeleteAll(d_ptr->syncHandlers);
184   d_ptr->syncMutex.unlock();
185
186   gst_object_unref(d_ptr->bus);
187
188   delete d_ptr; d_ptr = 0;
189 }
190
191 void QtCamGStreamerMessageListener::addHandler(QtCamGStreamerMessageHandler *handler) {
192   d_ptr->addHandler(handler, d_ptr->handlers);
193 }
194
195 void QtCamGStreamerMessageListener::removeHandler(QtCamGStreamerMessageHandler *handler) {
196   d_ptr->removeHandler(handler, d_ptr->handlers);
197 }
198
199 void QtCamGStreamerMessageListener::addSyncHandler(QtCamGStreamerMessageHandler *handler) {
200   QMutexLocker locker(&d_ptr->syncMutex);
201
202   d_ptr->addHandler(handler, d_ptr->syncHandlers);
203 }
204
205 void QtCamGStreamerMessageListener::removeSyncHandler(QtCamGStreamerMessageHandler *handler) {
206   QMutexLocker locker(&d_ptr->syncMutex);
207
208   d_ptr->removeHandler(handler, d_ptr->syncHandlers);
209 }
210
211 void QtCamGStreamerMessageListener::flushMessages() {
212   GstMessage *message = 0;
213
214   while ((message = gst_bus_pop(d_ptr->bus))) {
215     d_ptr->handleMessage(message);
216     gst_message_unref(message);
217   }
218 }