Music Hub ..
A session-wide music playback service
bus.h
Go to the documentation of this file.
1/*
2 * Copyright © 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */
18
19#ifndef GSTREAMER_BUS_H_
20#define GSTREAMER_BUS_H_
21
22#include <core/property.h>
23
24#include <gst/gst.h>
25
26#include <boost/flyweight.hpp>
27
28#include <exception>
29#include <functional>
30#include <memory>
31#include <tuple>
32
33namespace gstreamer
34{
35class Bus
36{
37public:
38 struct Message
39 {
41 {
42 }
43
44 Message(GstMessage* msg)
45 : message(msg),
46 type(GST_MESSAGE_TYPE(msg)),
47 source(GST_MESSAGE_SRC_NAME(msg)),
48 sequence_number(gst_message_get_seqnum(msg))
49 {
50 switch(type)
51 {
52 case GST_MESSAGE_UNKNOWN:
53 throw std::runtime_error("Cannot construct message for type unknown");
54 break;
55 case GST_MESSAGE_ERROR:
56 {
57 gst_message_parse_error(
58 msg,
61 cleanup = [this]()
62 {
63 g_error_free(detail.error_warning_info.error);
65 };
66 break;
67 }
68 case GST_MESSAGE_WARNING:
69 gst_message_parse_warning(
70 msg,
73 cleanup = [this]()
74 {
75 g_error_free(detail.error_warning_info.error);
77 };
78 break;
79 case GST_MESSAGE_INFO:
80 gst_message_parse_info(
81 msg,
84 cleanup = [this]()
85 {
86 g_error_free(detail.error_warning_info.error);
88 };
89 break;
90 case GST_MESSAGE_TAG:
91 gst_message_parse_tag(
92 msg,
94 cleanup = [this]()
95 {
96 gst_tag_list_unref(detail.tag.tag_list);
97 };
98 break;
99 case GST_MESSAGE_BUFFERING:
100 gst_message_parse_buffering(
101 msg,
103 break;
104 case GST_MESSAGE_STATE_CHANGED:
105 gst_message_parse_state_changed(
106 msg,
110 break;
111 case GST_MESSAGE_STEP_DONE:
112 gst_message_parse_step_done(
113 msg,
121 );
122 break;
123 case GST_MESSAGE_CLOCK_PROVIDE:
124 gst_message_parse_clock_provide(
125 msg,
128 break;
129 case GST_MESSAGE_CLOCK_LOST:
130 gst_message_parse_clock_lost(
131 msg,
133 break;
134 case GST_MESSAGE_NEW_CLOCK:
135 gst_message_parse_new_clock(
136 msg,
138 break;
139 case GST_MESSAGE_SEGMENT_START:
140 gst_message_parse_segment_start(
141 msg,
144 break;
145 case GST_MESSAGE_SEGMENT_DONE:
146 gst_message_parse_segment_done(
147 msg,
150 break;
151 case GST_MESSAGE_ASYNC_DONE:
152 gst_message_parse_async_done(
153 msg,
155 break;
156 case GST_MESSAGE_STEP_START:
157 gst_message_parse_step_start(
158 msg,
165 break;
166 case GST_MESSAGE_QOS:
167 gst_message_parse_qos(
168 msg,
169 &detail.qos.live,
174 break;
175 default:
176 break;
177 }
178 }
179
180 GstMessage* message;
181 GstMessageType type;
182 boost::flyweight<std::string> source;
184
185 union Detail
186 {
188 {
189 GError* error;
190 gchar* debug;
192 struct Tag
193 {
194 GstTagList* tag_list;
196 struct
197 {
200 struct
201 {
202 GstBufferingMode buffering_mode;
203 gint avg_in;
208 {
209 GstState old_state;
210 GstState new_state;
213 struct
214 {
215 gboolean active;
216 GstFormat format;
217 guint64 amount;
218 gdouble rate;
219 gboolean flush;
220 gboolean intermediate;
222 struct
223 {
224 GstFormat format;
225 guint64 amount;
226 gdouble rate;
227 gboolean flush;
228 gboolean intermediate;
229 guint64 duration;
230 gboolean eos;
232 struct
233 {
234 GstClock* clock;
235 gboolean ready;
237 struct
238 {
239 GstClock* clock;
241 struct
242 {
243 GstClock* clock;
245 struct
246 {
247 GstFormat format;
248 gint64 position;
250 struct
251 {
252 GstFormat format;
253 gint64 position;
255 struct
256 {
257 GstClockTime running_time;
259 struct
260 {
261 gboolean live;
263 guint64 stream_time;
264 guint64 timestamp;
265 guint64 duration;
268 std::function<void()> cleanup;
269 };
270
271 static GstBusSyncReply sync_handler(
272 GstBus* bus,
273 GstMessage* msg,
274 gpointer data)
275 {
276 (void) bus;
277
278 auto thiz = static_cast<Bus*>(data);
279 Message message(msg);
280 if (message.type == GST_MESSAGE_TAG || message.type == GST_MESSAGE_ASYNC_DONE)
281 thiz->on_new_message(message);
282
283 return GST_BUS_PASS;
284 }
285
286 static gboolean bus_watch_handler(
287 GstBus* bus,
288 GstMessage* msg,
289 gpointer data)
290 {
291 (void) bus;
292
293 auto thiz = static_cast<Bus*>(data);
294 Message message(msg);
295 thiz->on_new_message_async(message);
296
297 return true;
298 }
299
300 Bus(GstBus* bus) : bus(bus), bus_watch_id(0)
301 {
302 set_bus(bus);
303 }
304
306 {
307 g_source_remove(bus_watch_id);
308 gst_object_unref(bus);
309 }
310
311 void set_bus(GstBus* bus)
312 {
313 if (!bus)
314 throw std::runtime_error("Cannot create Bus instance if underlying instance is NULL.");
315
316 gst_bus_set_sync_handler(
317 bus,
319 this,
320 nullptr);
321
322 // Use a watch for most messages instead of the sync handler so that our context is not
323 // the same as the streaming thread, which can cause deadlocks in GStreamer
324 // if, for example, attempting to change the pipeline state from this context.
325 bus_watch_id = gst_bus_add_watch(
326 bus,
328 this);
329 }
330
331 GstBus* bus;
332 core::Signal<Message> on_new_message;
333 core::Signal<Message> on_new_message_async;
335};
336}
337
338#endif // GSTREAMER_BUS_H_
void set_bus(GstBus *bus)
Definition: bus.h:311
guint bus_watch_id
Definition: bus.h:334
Bus(GstBus *bus)
Definition: bus.h:300
static GstBusSyncReply sync_handler(GstBus *bus, GstMessage *msg, gpointer data)
Definition: bus.h:271
static gboolean bus_watch_handler(GstBus *bus, GstMessage *msg, gpointer data)
Definition: bus.h:286
GstBus * bus
Definition: bus.h:331
core::Signal< Message > on_new_message
Definition: bus.h:332
core::Signal< Message > on_new_message_async
Definition: bus.h:333
Definition: bus.h:34
GstMessageType type
Definition: bus.h:181
boost::flyweight< std::string > source
Definition: bus.h:182
union gstreamer::Bus::Message::Detail detail
std::function< void()> cleanup
Definition: bus.h:268
GstMessage * message
Definition: bus.h:180
Message(GstMessage *msg)
Definition: bus.h:44
uint32_t sequence_number
Definition: bus.h:183
struct gstreamer::Bus::Message::Detail::@5 clock_provide
struct gstreamer::Bus::Message::Detail::@7 clock_new
struct gstreamer::Bus::Message::Detail::@6 clock_lost
struct gstreamer::Bus::Message::Detail::ErrorWarningInfo error_warning_info
struct gstreamer::Bus::Message::Detail::@2 buffering_stats
struct gstreamer::Bus::Message::Detail::@4 step_done
struct gstreamer::Bus::Message::Detail::@10 async_done
struct gstreamer::Bus::Message::Detail::@9 segment_done
GstBufferingMode buffering_mode
Definition: bus.h:202
struct gstreamer::Bus::Message::Detail::Tag tag
struct gstreamer::Bus::Message::Detail::@11 qos
struct gstreamer::Bus::Message::Detail::@3 step_start
struct gstreamer::Bus::Message::Detail::StateChanged state_changed
struct gstreamer::Bus::Message::Detail::@8 segment_start
GstClockTime running_time
Definition: bus.h:257
struct gstreamer::Bus::Message::Detail::@1 buffering