Music Hub ..
A session-wide music playback service
Loading...
Searching...
No Matches
bus.h
Go to the documentation of this file.
1/*
2 * Copyright © 2013 Canonical Ltd.
3 * Copyright © 2022 UBports Foundation.
4 *
5 * Contact: Alberto Mardegan <mardy@users.sourceforge.net>
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License version 3,
9 * as published by the Free Software Foundation.
10 *
11 * This program 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
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Authored by: Thomas Voß <thomas.voss@canonical.com>
20 */
21
22#ifndef GSTREAMER_BUS_H
23#define GSTREAMER_BUS_H
24
25#include <gst/gst.h>
26
27#include <QByteArray>
28#include <QHash>
29
30#include <exception>
31#include <functional>
32#include <memory>
33
34namespace gstreamer
35{
36class Bus
37{
38public:
39 struct Message
40 {
42 {
43 }
44
45 Message(GstMessage* msg)
46 : message(msg),
47 type(GST_MESSAGE_TYPE(msg)),
48 source(GST_MESSAGE_SRC_NAME(msg)),
49 sequence_number(gst_message_get_seqnum(msg))
50 {
51 switch(type)
52 {
53 case GST_MESSAGE_UNKNOWN:
54 throw std::runtime_error("Cannot construct message for type unknown");
55 break;
56 case GST_MESSAGE_ERROR:
57 {
58 gst_message_parse_error(
59 msg,
60 &detail.error_warning_info.error,
61 &detail.error_warning_info.debug);
62 cleanup = [this]()
63 {
64 g_error_free(detail.error_warning_info.error);
65 g_free(detail.error_warning_info.debug);
66 };
67 break;
68 }
69 case GST_MESSAGE_WARNING:
70 gst_message_parse_warning(
71 msg,
72 &detail.error_warning_info.error,
73 &detail.error_warning_info.debug);
74 cleanup = [this]()
75 {
76 g_error_free(detail.error_warning_info.error);
77 g_free(detail.error_warning_info.debug);
78 };
79 break;
80 case GST_MESSAGE_INFO:
81 gst_message_parse_info(
82 msg,
83 &detail.error_warning_info.error,
84 &detail.error_warning_info.debug);
85 cleanup = [this]()
86 {
87 g_error_free(detail.error_warning_info.error);
88 g_free(detail.error_warning_info.debug);
89 };
90 break;
91 case GST_MESSAGE_TAG:
92 gst_message_parse_tag(
93 msg,
94 &detail.tag.tag_list);
95 cleanup = [this]()
96 {
97 gst_tag_list_unref(detail.tag.tag_list);
98 };
99 break;
100 case GST_MESSAGE_BUFFERING:
101 gst_message_parse_buffering(
102 msg,
103 &detail.buffering.percent);
104 break;
105 case GST_MESSAGE_STATE_CHANGED:
106 gst_message_parse_state_changed(
107 msg,
108 &detail.state_changed.old_state,
109 &detail.state_changed.new_state,
110 &detail.state_changed.pending_state);
111 break;
112 case GST_MESSAGE_STEP_DONE:
113 gst_message_parse_step_done(
114 msg,
115 &detail.step_done.format,
116 &detail.step_done.amount,
117 &detail.step_done.rate,
118 &detail.step_done.flush,
119 &detail.step_done.intermediate,
120 &detail.step_done.duration,
121 &detail.step_done.eos
122 );
123 break;
124 case GST_MESSAGE_CLOCK_PROVIDE:
125 gst_message_parse_clock_provide(
126 msg,
127 &detail.clock_provide.clock,
128 &detail.clock_provide.ready);
129 break;
130 case GST_MESSAGE_CLOCK_LOST:
131 gst_message_parse_clock_lost(
132 msg,
133 &detail.clock_lost.clock);
134 break;
135 case GST_MESSAGE_NEW_CLOCK:
136 gst_message_parse_new_clock(
137 msg,
138 &detail.clock_new.clock);
139 break;
140 case GST_MESSAGE_SEGMENT_START:
141 gst_message_parse_segment_start(
142 msg,
143 &detail.segment_start.format,
144 &detail.segment_start.position);
145 break;
146 case GST_MESSAGE_SEGMENT_DONE:
147 gst_message_parse_segment_done(
148 msg,
149 &detail.segment_done.format,
150 &detail.segment_done.position);
151 break;
152 case GST_MESSAGE_ASYNC_DONE:
153 gst_message_parse_async_done(
154 msg,
155 &detail.async_done.running_time);
156 break;
157 case GST_MESSAGE_STEP_START:
158 gst_message_parse_step_start(
159 msg,
160 &detail.step_start.active,
161 &detail.step_start.format,
162 &detail.step_start.amount,
163 &detail.step_start.rate,
164 &detail.step_start.flush,
165 &detail.step_start.intermediate);
166 break;
167 case GST_MESSAGE_QOS:
168 gst_message_parse_qos(
169 msg,
170 &detail.qos.live,
171 &detail.qos.running_time,
172 &detail.qos.stream_time,
173 &detail.qos.timestamp,
174 &detail.qos.duration);
175 break;
176 default:
177 break;
178 }
179 }
180
181 GstMessage* message;
182 GstMessageType type;
183 QByteArray source; // TODO compute it only when needed
185
186 union Detail
187 {
195 struct Tag
196 {
197 Tag(const Tag &t): tag_list(gst_tag_list_ref(t.tag_list)) {}
198 ~Tag() { gst_tag_list_unref(tag_list); }
199 GstTagList* tag_list;
201 struct
202 {
205 struct
206 {
207 GstBufferingMode buffering_mode;
208 gint avg_in;
213 {
214 GstState old_state;
215 GstState new_state;
218 struct
219 {
220 gboolean active;
221 GstFormat format;
222 guint64 amount;
223 gdouble rate;
224 gboolean flush;
225 gboolean intermediate;
227 struct
228 {
229 GstFormat format;
230 guint64 amount;
231 gdouble rate;
232 gboolean flush;
233 gboolean intermediate;
234 guint64 duration;
235 gboolean eos;
237 struct
238 {
239 GstClock* clock;
240 gboolean ready;
242 struct
243 {
244 GstClock* clock;
246 struct
247 {
248 GstClock* clock;
250 struct
251 {
252 GstFormat format;
253 gint64 position;
255 struct
256 {
257 GstFormat format;
258 gint64 position;
260 struct
261 {
262 GstClockTime running_time;
264 struct
265 {
266 gboolean live;
268 guint64 stream_time;
269 guint64 timestamp;
270 guint64 duration;
273 std::function<void()> cleanup;
274 };
275
276 static gboolean bus_watch_handler(
277 GstBus* bus,
278 GstMessage* msg,
279 gpointer data)
280 {
281 (void) bus;
282
283 auto thiz = static_cast<Bus*>(data);
284 Message message(msg);
285 thiz->notifyNewMessage(message);
286
287 return true;
288 }
289
290 Bus(GstBus* bus):
291 bus(bus),
293 bus_watch_id(0)
294 {
295 set_bus(bus);
296 }
297
299 {
300 g_source_remove(bus_watch_id);
301 gst_object_unref(bus);
302 }
303
304 void set_bus(GstBus* bus)
305 {
306 if (!bus)
307 throw std::runtime_error("Cannot create Bus instance if underlying instance is NULL.");
308
309 // Use a watch for most messages instead of the sync handler so that our context is not
310 // the same as the streaming thread, which can cause deadlocks in GStreamer
311 // if, for example, attempting to change the pipeline state from this context.
312 bus_watch_id = gst_bus_add_watch(
313 bus,
315 this);
316 }
317
318 typedef std::function<void(const Message &)> MessageCallback;
319
324
326 m_onNewMessage.remove(id);
327 }
328
329 void notifyNewMessage(const Message &msg) const {
330 for (auto cb: m_onNewMessage) {
331 cb(msg);
332 }
333 }
334
335 GstBus* bus;
336 QHash<int,MessageCallback> m_onNewMessage;
339};
340}
341
342#endif // GSTREAMER_BUS_H
std::function< void(const Message &)> MessageCallback
Definition bus.h:318
void set_bus(GstBus *bus)
Definition bus.h:304
guint bus_watch_id
Definition bus.h:338
int onNewMessage(const MessageCallback &cb)
Definition bus.h:320
QHash< int, MessageCallback > m_onNewMessage
Definition bus.h:336
Bus(GstBus *bus)
Definition bus.h:290
void notifyNewMessage(const Message &msg) const
Definition bus.h:329
void unsubscribeFromNewMessage(int id)
Definition bus.h:325
int m_onNewMessageNextId
Definition bus.h:337
static gboolean bus_watch_handler(GstBus *bus, GstMessage *msg, gpointer data)
Definition bus.h:276
GstBus * bus
Definition bus.h:335
GstMessageType type
Definition bus.h:182
union gstreamer::Bus::Message::Detail detail
std::function< void()> cleanup
Definition bus.h:273
QByteArray source
Definition bus.h:183
GstMessage * message
Definition bus.h:181
Message(GstMessage *msg)
Definition bus.h:45
uint32_t sequence_number
Definition bus.h:184
struct gstreamer::Bus::Message::Detail::@010356011203302032001076175110203066312255320253 segment_start
struct gstreamer::Bus::Message::Detail::@274275267153007126244075115121106367210121250272 clock_lost
struct gstreamer::Bus::Message::Detail::@111315325006364174317064000232216307101104116242 step_done
struct gstreamer::Bus::Message::Detail::ErrorWarningInfo error_warning_info
struct gstreamer::Bus::Message::Detail::@077251127256044244012032243134322167176332257044 step_start
struct gstreamer::Bus::Message::Detail::@117017075015211113114163235017052171171152075050 segment_done
struct gstreamer::Bus::Message::Detail::@216063064125204302033061063153176142220321363155 clock_new
GstBufferingMode buffering_mode
Definition bus.h:207
struct gstreamer::Bus::Message::Detail::@203355045217106207217157264131266354272037264245 async_done
struct gstreamer::Bus::Message::Detail::Tag tag
struct gstreamer::Bus::Message::Detail::@244334144313267103037240204336045201140371063356 buffering_stats
struct gstreamer::Bus::Message::Detail::StateChanged state_changed
struct gstreamer::Bus::Message::Detail::@052111310100141373364352234203071073257145067336 qos
struct gstreamer::Bus::Message::Detail::@316142226061143042354256367365343175141143307364 clock_provide
GstClockTime running_time
Definition bus.h:262
struct gstreamer::Bus::Message::Detail::@173145016337074143037121042161013173000171136375 buffering