diff --git a/src/lib/clapper/clapper-app-bus-private.h b/src/lib/clapper/clapper-app-bus-private.h index 6f53dee4..b3c03d4d 100644 --- a/src/lib/clapper/clapper-app-bus-private.h +++ b/src/lib/clapper/clapper-app-bus-private.h @@ -52,6 +52,8 @@ void clapper_app_bus_post_object_desc_signal (ClapperAppBus *app_bus, GstObject void clapper_app_bus_post_desc_with_details_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, const gchar *desc, const gchar *details); +void clapper_app_bus_post_message_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, GstMessage *msg); + void clapper_app_bus_post_error_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, GError *error, const gchar *debug_info); G_END_DECLS diff --git a/src/lib/clapper/clapper-app-bus.c b/src/lib/clapper/clapper-app-bus.c index b70e4fd1..b1d961af 100644 --- a/src/lib/clapper/clapper-app-bus.c +++ b/src/lib/clapper/clapper-app-bus.c @@ -46,6 +46,7 @@ enum CLAPPER_APP_BUS_STRUCTURE_SIMPLE_SIGNAL, CLAPPER_APP_BUS_STRUCTURE_OBJECT_DESC_SIGNAL, CLAPPER_APP_BUS_STRUCTURE_DESC_WITH_DETAILS_SIGNAL, + CLAPPER_APP_BUS_STRUCTURE_MESSAGE_SIGNAL, CLAPPER_APP_BUS_STRUCTURE_ERROR_SIGNAL }; @@ -58,6 +59,7 @@ static ClapperBusQuark _structure_quarks[] = { {"simple-signal", 0}, {"object-desc-signal", 0}, {"desc-with-details-signal", 0}, + {"message", 0}, {"error-signal", 0}, {NULL, 0} }; @@ -276,6 +278,53 @@ _handle_desc_with_details_signal_msg (GstMessage *msg, const GstStructure *struc g_free (details); } +void +clapper_app_bus_post_message_signal (ClapperAppBus *self, + GstObject *src, guint signal_id, GstMessage *msg) +{ + /* Check for any "message" signal connection */ + if (g_signal_handler_find (src, G_SIGNAL_MATCH_ID, + signal_id, 0, NULL, NULL, NULL) != 0) { + const GstStructure *structure = gst_message_get_structure (msg); + GQuark detail; + + if (G_UNLIKELY (structure == NULL)) + return; + + detail = g_quark_from_string (gst_structure_get_name (structure)); + + /* If specific detail is connected or ALL "message" handler */ + if (g_signal_handler_find (src, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL, + signal_id, detail, NULL, NULL, NULL) != 0 + || g_signal_handler_find (src, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL, + signal_id, 0, NULL, NULL, NULL) != 0) { + GstStructure *structure = gst_structure_new_id (_STRUCTURE_QUARK (MESSAGE_SIGNAL), + _FIELD_QUARK (SIGNAL_ID), G_TYPE_UINT, signal_id, + _FIELD_QUARK (DETAILS), G_TYPE_UINT, detail, + _FIELD_QUARK (OBJECT), GST_TYPE_MESSAGE, msg, + NULL); + gst_bus_post (GST_BUS_CAST (self), gst_message_new_application (src, structure)); + } + } +} + +static inline void +_handle_message_signal_msg (GstMessage *msg, const GstStructure *structure) +{ + guint signal_id = 0; + GQuark detail = 0; + GstMessage *fwd_message = NULL; + + gst_structure_id_get (structure, + _FIELD_QUARK (SIGNAL_ID), G_TYPE_UINT, &signal_id, + _FIELD_QUARK (DETAILS), G_TYPE_UINT, &detail, + _FIELD_QUARK (OBJECT), GST_TYPE_MESSAGE, &fwd_message, + NULL); + g_signal_emit (_MESSAGE_SRC_GOBJECT (msg), signal_id, detail, fwd_message); + + gst_message_unref (fwd_message); +} + void clapper_app_bus_post_error_signal (ClapperAppBus *self, GstObject *src, guint signal_id, @@ -326,6 +375,8 @@ clapper_app_bus_message_func (GstBus *bus, GstMessage *msg, gpointer user_data G _handle_simple_signal_msg (msg, structure); else if (quark == _STRUCTURE_QUARK (OBJECT_DESC_SIGNAL)) _handle_object_desc_signal_msg (msg, structure); + else if (quark == _STRUCTURE_QUARK (MESSAGE_SIGNAL)) + _handle_message_signal_msg (msg, structure); else if (quark == _STRUCTURE_QUARK (ERROR_SIGNAL)) _handle_error_signal_msg (msg, structure); else if (quark == _STRUCTURE_QUARK (DESC_WITH_DETAILS_SIGNAL)) diff --git a/src/lib/clapper/clapper-playbin-bus.c b/src/lib/clapper/clapper-playbin-bus.c index 4cb6a1c5..706d080b 100644 --- a/src/lib/clapper/clapper-playbin-bus.c +++ b/src/lib/clapper/clapper-playbin-bus.c @@ -930,6 +930,11 @@ _handle_element_msg (GstMessage *msg, ClapperPlayer *player) GST_OBJECT_CAST (downloaded_item), location); gst_object_unref (downloaded_item); + } else { + guint signal_id = g_signal_lookup ("message", CLAPPER_TYPE_PLAYER); + + clapper_app_bus_post_message_signal (player->app_bus, + GST_OBJECT_CAST (player), signal_id, msg); } } diff --git a/src/lib/clapper/clapper-player.c b/src/lib/clapper/clapper-player.c index d01868c5..39dee096 100644 --- a/src/lib/clapper/clapper-player.c +++ b/src/lib/clapper/clapper-player.c @@ -111,6 +111,7 @@ enum SIGNAL_SEEK_DONE, SIGNAL_DOWNLOAD_COMPLETE, SIGNAL_MISSING_PLUGIN, + SIGNAL_MESSAGE, SIGNAL_WARNING, SIGNAL_ERROR, SIGNAL_LAST @@ -2985,6 +2986,28 @@ clapper_player_class_init (ClapperPlayerClass *klass) G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); + /** + * ClapperPlayer::message: + * @player: a #ClapperPlayer + * @msg: a #GstMessage + * + * Allows for applications to receive element messages posted + * on the underlaying pipeline bus. + * + * This is a detailed signal. Connect to it via `message::name` + * to only receive messages with a certain `name`. + * + * Player will only forward messages to the main app thread (from which + * this signal is emitted) that have a matching signal handler, thus + * it is more efficient to listen only for specific messages instead + * of connecting to simply `message` with no details (without message name). + * + * Since: 0.10 + */ + signals[SIGNAL_MESSAGE] = g_signal_new ("message", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS | G_SIGNAL_DETAILED, + 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_MESSAGE); + /** * ClapperPlayer::warning: * @player: a #ClapperPlayer