static void handle_missing_plugin_message (RBPlayerGst *player, GstMessage *message) { char **details; char **descriptions; char *detail; char *description; int count; rb_debug ("got missing-plugin message from %s: %s", GST_OBJECT_NAME (GST_MESSAGE_SRC (message)), gst_missing_plugin_message_get_installer_detail (message)); /* probably need to wait to collect any subsequent missing-plugin * messages, but I think we'd need to wait for state changes to do * that. for now, we can only handle a single message. */ count = 1; details = g_new0 (char *, count + 1); descriptions = g_new0 (char *, count + 1); detail = gst_missing_plugin_message_get_installer_detail (message); description = gst_missing_plugin_message_get_description (message); details[0] = g_strdup (detail); descriptions[0] = g_strdup (description); g_signal_emit (player, signals[MISSING_PLUGINS], 0, player->priv->stream_data, details, descriptions); g_strfreev (details); g_strfreev (descriptions); }
static VALUE missing_message_get_description(VALUE self) { gchar *description; description = gst_missing_plugin_message_get_description(SELF(self)); return CSTR2RVAL_FREE(description); }
static void missing_msg_check_getters (GstMessage * msg) { gchar *str; str = gst_missing_plugin_message_get_installer_detail (msg); fail_unless (str != NULL); fail_unless (*str != '\0'); fail_unless (g_str_has_prefix (str, "gstreamer|")); g_free (str); str = gst_missing_plugin_message_get_description (msg); fail_unless (str != NULL); fail_unless (*str != '\0'); g_free (str); }
static gboolean play_bus_msg (GstBus * bus, GstMessage * msg, gpointer user_data) { GstPlay *play = user_data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ASYNC_DONE: /* dump graph on preroll */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.async-done"); g_print ("Prerolled.\r"); if (play->missing != NULL && play_install_missing_plugins (play)) { g_print ("New plugins installed, trying again...\n"); --play->cur_idx; play_next (play); } break; case GST_MESSAGE_BUFFERING:{ gint percent; if (!play->buffering) g_print ("\n"); gst_message_parse_buffering (msg, &percent); g_print ("%s %d%% \r", _("Buffering..."), percent); if (percent == 100) { /* a 100% message means buffering is done */ if (play->buffering) { play->buffering = FALSE; /* no state management needed for live pipelines */ if (!play->is_live) gst_element_set_state (play->playbin, play->desired_state); } } else { /* buffering... */ if (!play->buffering) { if (!play->is_live) gst_element_set_state (play->playbin, GST_STATE_PAUSED); play->buffering = TRUE; } } break; } case GST_MESSAGE_CLOCK_LOST:{ g_print (_("Clock lost, selecting a new one\n")); gst_element_set_state (play->playbin, GST_STATE_PAUSED); gst_element_set_state (play->playbin, GST_STATE_PLAYING); break; } case GST_MESSAGE_LATENCY: g_print ("Redistribute latency...\n"); gst_bin_recalculate_latency (GST_BIN (play->playbin)); break; case GST_MESSAGE_REQUEST_STATE:{ GstState state; gchar *name; name = gst_object_get_path_string (GST_MESSAGE_SRC (msg)); gst_message_parse_request_state (msg, &state); g_print ("Setting state to %s as requested by %s...\n", gst_element_state_get_name (state), name); gst_element_set_state (play->playbin, state); g_free (name); break; } case GST_MESSAGE_EOS: /* print final position at end */ play_timeout (play); g_print ("\n"); /* and switch to next item in list */ if (!play_next (play)) { g_print ("%s\n", _("Reached end of play list.")); g_main_loop_quit (play->loop); } break; case GST_MESSAGE_WARNING:{ GError *err; gchar *dbg = NULL; /* dump graph on warning */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.warning"); gst_message_parse_warning (msg, &err, &dbg); g_printerr ("WARNING %s\n", err->message); if (dbg != NULL) g_printerr ("WARNING debug information: %s\n", dbg); g_clear_error (&err); g_free (dbg); break; } case GST_MESSAGE_ERROR:{ GError *err; gchar *dbg; /* dump graph on error */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.error"); gst_message_parse_error (msg, &err, &dbg); g_printerr ("ERROR %s for %s\n", err->message, play->uris[play->cur_idx]); if (dbg != NULL) g_printerr ("ERROR debug information: %s\n", dbg); g_clear_error (&err); g_free (dbg); /* flush any other error messages from the bus and clean up */ gst_element_set_state (play->playbin, GST_STATE_NULL); if (play->missing != NULL && play_install_missing_plugins (play)) { g_print ("New plugins installed, trying again...\n"); --play->cur_idx; play_next (play); break; } /* try next item in list then */ if (!play_next (play)) { g_print ("%s\n", _("Reached end of play list.")); g_main_loop_quit (play->loop); } break; } case GST_MESSAGE_ELEMENT: { GstNavigationMessageType mtype = gst_navigation_message_get_type (msg); if (mtype == GST_NAVIGATION_MESSAGE_EVENT) { GstEvent *ev = NULL; if (gst_navigation_message_parse_event (msg, &ev)) { GstNavigationEventType e_type = gst_navigation_event_get_type (ev); switch (e_type) { case GST_NAVIGATION_EVENT_KEY_PRESS: { const gchar *key; if (gst_navigation_event_parse_key_event (ev, &key)) { GST_INFO ("Key press: %s", key); if (strcmp (key, "Left") == 0) key = GST_PLAY_KB_ARROW_LEFT; else if (strcmp (key, "Right") == 0) key = GST_PLAY_KB_ARROW_RIGHT; else if (strcmp (key, "Up") == 0) key = GST_PLAY_KB_ARROW_UP; else if (strcmp (key, "Down") == 0) key = GST_PLAY_KB_ARROW_DOWN; else if (strcmp (key, "space") == 0) key = " "; else if (strlen (key) > 1) break; keyboard_cb (key, user_data); } break; } case GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS: { gint button; if (gst_navigation_event_parse_mouse_button_event (ev, &button, NULL, NULL)) { if (button == 4) { /* wheel up */ relative_seek (play, +0.08); } else if (button == 5) { /* wheel down */ relative_seek (play, -0.01); } } break; } default: break; } } if (ev) gst_event_unref (ev); } break; } default: if (gst_is_missing_plugin_message (msg)) { gchar *desc; desc = gst_missing_plugin_message_get_description (msg); g_print ("Missing plugin: %s\n", desc); g_free (desc); play->missing = g_list_append (play->missing, gst_message_ref (msg)); } break; } return TRUE; }
static gboolean play_bus_msg (GstBus * bus, GstMessage * msg, gpointer user_data) { GstPlay *play = user_data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ASYNC_DONE: /* dump graph on preroll */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.async-done"); g_print ("Prerolled.\r"); if (play->missing != NULL && play_install_missing_plugins (play)) { g_print ("New plugins installed, trying again...\n"); --play->cur_idx; play_next (play); } break; case GST_MESSAGE_BUFFERING:{ gint percent; if (!play->buffering) g_print ("\n"); gst_message_parse_buffering (msg, &percent); g_print ("%s %d%% \r", _("Buffering..."), percent); if (percent == 100) { /* a 100% message means buffering is done */ if (play->buffering) { play->buffering = FALSE; /* no state management needed for live pipelines */ if (!play->is_live) gst_element_set_state (play->playbin, play->desired_state); } } else { /* buffering... */ if (!play->buffering) { if (!play->is_live) gst_element_set_state (play->playbin, GST_STATE_PAUSED); play->buffering = TRUE; } } break; } case GST_MESSAGE_CLOCK_LOST:{ g_print (_("Clock lost, selecting a new one\n")); gst_element_set_state (play->playbin, GST_STATE_PAUSED); gst_element_set_state (play->playbin, GST_STATE_PLAYING); break; } case GST_MESSAGE_LATENCY: g_print ("Redistribute latency...\n"); gst_bin_recalculate_latency (GST_BIN (play->playbin)); break; case GST_MESSAGE_REQUEST_STATE:{ GstState state; gchar *name; name = gst_object_get_path_string (GST_MESSAGE_SRC (msg)); gst_message_parse_request_state (msg, &state); g_print ("Setting state to %s as requested by %s...\n", gst_element_state_get_name (state), name); gst_element_set_state (play->playbin, state); g_free (name); break; } case GST_MESSAGE_EOS: /* print final position at end */ play_timeout (play); g_print ("\n"); /* and switch to next item in list */ if (!play_next (play)) { g_print ("Reached end of play list.\n"); g_main_loop_quit (play->loop); } break; case GST_MESSAGE_WARNING:{ GError *err; gchar *dbg = NULL; /* dump graph on warning */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.warning"); gst_message_parse_warning (msg, &err, &dbg); g_printerr ("WARNING %s\n", err->message); if (dbg != NULL) g_printerr ("WARNING debug information: %s\n", dbg); g_error_free (err); g_free (dbg); break; } case GST_MESSAGE_ERROR:{ GError *err; gchar *dbg; /* dump graph on error */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin), GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.error"); gst_message_parse_error (msg, &err, &dbg); g_printerr ("ERROR %s for %s\n", err->message, play->uris[play->cur_idx]); if (dbg != NULL) g_printerr ("ERROR debug information: %s\n", dbg); g_error_free (err); g_free (dbg); /* flush any other error messages from the bus and clean up */ gst_element_set_state (play->playbin, GST_STATE_NULL); if (play->missing != NULL && play_install_missing_plugins (play)) { g_print ("New plugins installed, trying again...\n"); --play->cur_idx; play_next (play); break; } /* try next item in list then */ if (!play_next (play)) { g_print ("Reached end of play list.\n"); g_main_loop_quit (play->loop); } break; } default: if (gst_is_missing_plugin_message (msg)) { gchar *desc; desc = gst_missing_plugin_message_get_description (msg); g_print ("Missing plugin: %s\n", desc); g_free (desc); play->missing = g_list_append (play->missing, gst_message_ref (msg)); } break; } return TRUE; }
G_MODULE_EXPORT gboolean live_preview_cb(GstBus *bus, GstMessage *msg, gpointer data) { signal_user_data_t *ud = (signal_user_data_t*)data; switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_UNKNOWN: { //printf("unknown"); } break; case GST_MESSAGE_EOS: { // Done //printf("eos\n"); live_preview_stop(ud); gst_element_seek(ud->preview->play, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); } break; case GST_MESSAGE_ERROR: { //printf("error\n"); GError *err; gchar *debug; gst_message_parse_error(msg, &err, &debug); g_warning("Gstreamer Error: %s", err->message); g_error_free(err); g_free(debug); } break; case GST_MESSAGE_WARNING: case GST_MESSAGE_INFO: case GST_MESSAGE_TAG: case GST_MESSAGE_BUFFERING: case GST_MESSAGE_STATE_CHANGED: { //printf("state change %x\n", state); GstState state, pending; gst_element_get_state(ud->preview->play, &state, &pending, 0); if (state == GST_STATE_PAUSED || state == GST_STATE_PLAYING) { update_stream_info(ud); } } break; case GST_MESSAGE_STATE_DIRTY: { //printf("state dirty\n"); } break; case GST_MESSAGE_STEP_DONE: { //printf("step done\n"); } break; case GST_MESSAGE_CLOCK_PROVIDE: { //printf("clock provide\n"); } break; case GST_MESSAGE_CLOCK_LOST: { //printf("clock lost\n"); } break; case GST_MESSAGE_NEW_CLOCK: { //printf("new clock\n"); } break; case GST_MESSAGE_STRUCTURE_CHANGE: { //printf("structure change\n"); } break; case GST_MESSAGE_STREAM_STATUS: { //printf("stream status\n"); } break; case GST_MESSAGE_APPLICATION: { //printf("application\n"); } break; case GST_MESSAGE_ELEMENT: { //printf("element\n"); if (gst_is_missing_plugin_message(msg)) { GtkWindow *hb_window; hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window")); gst_element_set_state(ud->preview->play, GST_STATE_PAUSED); gchar *message, *desc; desc = gst_missing_plugin_message_get_description(msg); message = g_strdup_printf( _("Missing GStreamer plugin\n" "Audio or Video may not play as expected\n\n%s"), desc); ghb_message_dialog(hb_window, GTK_MESSAGE_WARNING, message, "Ok", NULL); g_free(message); gst_element_set_state(ud->preview->play, GST_STATE_PLAYING); } else if (msg->src == GST_OBJECT_CAST(ud->preview->vsink)) { const GstStructure *gstStruct; const GValue *val; gstStruct = gst_message_get_structure(msg); if (gstStruct != NULL && (gst_structure_has_name(gstStruct, "preroll-pixbuf") || gst_structure_has_name(gstStruct, "pixbuf"))) { val = gst_structure_get_value(gstStruct, "pixbuf"); if (val != NULL) { GdkPixbuf * pix; GtkWidget *widget; int width, height; if (ud->preview->pix != NULL) g_object_unref(ud->preview->pix); if (ud->preview->scaled_pix != NULL) g_object_unref(ud->preview->scaled_pix); pix = GDK_PIXBUF(g_value_dup_object(val)); width = gdk_pixbuf_get_width(pix); height = gdk_pixbuf_get_height(pix); if (width != ud->preview->width || height != ud->preview->height || width != ud->preview->render_width || height != ud->preview->render_height) { double xscale, yscale; xscale = (double)ud->preview->render_width / ud->preview->width; yscale = (double)ud->preview->render_height / ud->preview->height; if (xscale <= yscale) { width = ud->preview->render_width; height = ud->preview->height * xscale; } else { width = ud->preview->width * yscale; height = ud->preview->render_height; } ud->preview->scaled_pix = gdk_pixbuf_scale_simple(pix, width, height, GDK_INTERP_BILINEAR); g_object_ref(pix); } else { ud->preview->scaled_pix = pix; } ud->preview->pix = ud->preview->scaled_pix; g_object_ref(ud->preview->pix); widget = GHB_WIDGET (ud->builder, "preview_image"); gtk_widget_queue_draw(widget); } } } } break; case GST_MESSAGE_SEGMENT_START: { //printf("segment start\n"); } break; case GST_MESSAGE_SEGMENT_DONE: { //printf("segment done\n"); } break; case GST_MESSAGE_DURATION_CHANGED: { //printf("duration change\n"); }; case GST_MESSAGE_LATENCY: { //printf("latency\n"); }; case GST_MESSAGE_ASYNC_START: { //printf("async start\n"); } break; case GST_MESSAGE_ASYNC_DONE: { //printf("async done\n"); } break; case GST_MESSAGE_REQUEST_STATE: { //printf("request state\n"); } break; case GST_MESSAGE_STEP_START: { //printf("step start\n"); } break; case GST_MESSAGE_QOS: { //printf("qos\n"); } break; case GST_MESSAGE_PROGRESS: { //printf("progress\n"); } break; case GST_MESSAGE_TOC: { //printf("toc\n"); } break; case GST_MESSAGE_RESET_TIME: { //printf("reset time\n"); } break; case GST_MESSAGE_STREAM_START: { //printf("stream start\n"); }; case GST_MESSAGE_ANY: { //printf("any\n"); } break; default: { // Ignore //printf("?msg? %x\n", GST_MESSAGE_TYPE(msg)); } } return TRUE; }
/** * gst_missing_plugin_message_get_installer_detail: * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT * * Returns an opaque string containing all the details about the missing * element to be passed to an external installer called via * gst_install_plugins_async() or gst_install_plugins_sync(). * * This function is mainly for applications that call external plugin * installation mechanisms using one of the two above-mentioned functions. * * Returns: a newly-allocated detail string, or NULL on error. Free string * with g_free() when not needed any longer. */ gchar * gst_missing_plugin_message_get_installer_detail (GstMessage * msg) { GstMissingType missing_type; const gchar *progname; const gchar *type; GString *str = NULL; gchar *detail = NULL; gchar *desc; g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL); GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, msg->structure); missing_type = missing_structure_get_type (msg->structure); if (missing_type == GST_MISSING_TYPE_UNKNOWN) { GST_WARNING ("couldn't parse 'type' field"); goto error; } type = gst_structure_get_string (msg->structure, "type"); g_assert (type != NULL); /* validity already checked above */ /* FIXME: use gst_installer_detail_new() here too */ str = g_string_new (GST_DETAIL_STRING_MARKER "|"); g_string_append_printf (str, "%u.%u|", GST_VERSION_MAJOR, GST_VERSION_MINOR); progname = (const gchar *) g_get_prgname (); if (progname) { g_string_append_printf (str, "%s|", progname); } else { g_string_append_printf (str, "pid/%lu|", (gulong) getpid ()); } desc = gst_missing_plugin_message_get_description (msg); if (desc) { g_strdelimit (desc, "|", '#'); g_string_append_printf (str, "%s|", desc); g_free (desc); } else { g_string_append (str, "|"); } switch (missing_type) { case GST_MISSING_TYPE_URISOURCE: case GST_MISSING_TYPE_URISINK: case GST_MISSING_TYPE_ELEMENT: if (!missing_structure_get_string_detail (msg->structure, &detail)) goto error; break; case GST_MISSING_TYPE_DECODER: case GST_MISSING_TYPE_ENCODER:{ GstCaps *caps = NULL; if (!missing_structure_get_caps_detail (msg->structure, &caps)) goto error; detail = gst_caps_to_string (caps); gst_caps_unref (caps); break; } default: g_return_val_if_reached (NULL); } g_string_append_printf (str, "%s-%s", type, detail); g_free (detail); return g_string_free (str, FALSE); /* ERRORS */ error: { GST_WARNING ("Failed to parse missing-plugin msg: %" GST_PTR_FORMAT, msg); if (str) g_string_free (str, TRUE); return NULL; } }
void eServiceMP3::gstBusCall(GstMessage *msg) { if (!msg) return; gchar *sourceName; GstObject *source; source = GST_MESSAGE_SRC(msg); if (!GST_IS_OBJECT(source)) return; sourceName = gst_object_get_name(source); #if 0 gchar *string; if (gst_message_get_structure(msg)) string = gst_structure_to_string(gst_message_get_structure(msg)); else string = g_strdup(GST_MESSAGE_TYPE_NAME(msg)); eDebug("eTsRemoteSource::gst_message from %s: %s", sourceName, string); g_free(string); #endif switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: m_event((iPlayableService*)this, evEOF); break; case GST_MESSAGE_STATE_CHANGED: { if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) break; GstState old_state, new_state; gst_message_parse_state_changed(msg, &old_state, &new_state, NULL); if(old_state == new_state) break; eDebug("eServiceMP3::state transition %s -> %s", gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state); switch(transition) { case GST_STATE_CHANGE_NULL_TO_READY: { } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { GstElement *subsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); if (subsink) { #ifdef GSTREAMER_SUBTITLE_SYNC_MODE_BUG /* * HACK: disable sync mode for now, gstreamer suffers from a bug causing sparse streams to loose sync, after pause/resume / skip * see: https://bugzilla.gnome.org/show_bug.cgi?id=619434 * Sideeffect of using sync=false is that we receive subtitle buffers (far) ahead of their * display time. * Not too far ahead for subtitles contained in the media container. * But for external srt files, we could receive all subtitles at once. * And not just once, but after each pause/resume / skip. * So as soon as gstreamer has been fixed to keep sync in sparse streams, sync needs to be re-enabled. */ g_object_set (G_OBJECT (subsink), "sync", FALSE, NULL); #endif #if 0 /* we should not use ts-offset to sync with the decoder time, we have to do our own decoder timekeeping */ g_object_set (G_OBJECT (subsink), "ts-offset", -2L * GST_SECOND, NULL); /* late buffers probably will not occur very often */ g_object_set (G_OBJECT (subsink), "max-lateness", 0L, NULL); /* avoid prerolling (it might not be a good idea to preroll a sparse stream) */ g_object_set (G_OBJECT (subsink), "async", TRUE, NULL); #endif eDebug("eServiceMP3::subsink properties set!"); gst_object_unref(subsink); } setAC3Delay(ac3_delay); setPCMDelay(pcm_delay); } break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { if ( m_sourceinfo.is_streaming && m_streamingsrc_timeout ) m_streamingsrc_timeout->stop(); } break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: { } break; case GST_STATE_CHANGE_PAUSED_TO_READY: { } break; case GST_STATE_CHANGE_READY_TO_NULL: { } break; } break; } case GST_MESSAGE_ERROR: { gchar *debug; GError *err; gst_message_parse_error (msg, &err, &debug); g_free (debug); eWarning("Gstreamer error: %s (%i) from %s", err->message, err->code, sourceName ); if ( err->domain == GST_STREAM_ERROR ) { if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND ) { if ( g_strrstr(sourceName, "videosink") ) m_event((iPlayableService*)this, evUser+11); else if ( g_strrstr(sourceName, "audiosink") ) m_event((iPlayableService*)this, evUser+10); } } g_error_free(err); break; } case GST_MESSAGE_INFO: { gchar *debug; GError *inf; gst_message_parse_info (msg, &inf, &debug); g_free (debug); if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE ) { if ( g_strrstr(sourceName, "videosink") ) m_event((iPlayableService*)this, evUser+14); } g_error_free(inf); break; } case GST_MESSAGE_TAG: { GstTagList *tags, *result; gst_message_parse_tag(msg, &tags); result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE); if (result) { if (m_stream_tags) gst_tag_list_free(m_stream_tags); m_stream_tags = result; } const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0); if ( gv_image ) { GstBuffer *buf_image; buf_image = gst_value_get_buffer (gv_image); int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644); int ret = write(fd, GST_BUFFER_DATA(buf_image), GST_BUFFER_SIZE(buf_image)); close(fd); eDebug("eServiceMP3::/tmp/.id3coverart %d bytes written ", ret); m_event((iPlayableService*)this, evUser+13); } gst_tag_list_free(tags); m_event((iPlayableService*)this, evUpdatedInfo); break; } case GST_MESSAGE_ASYNC_DONE: { if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) break; GstTagList *tags; gint i, active_idx, n_video = 0, n_audio = 0, n_text = 0; g_object_get (m_gst_playbin, "n-video", &n_video, NULL); g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL); g_object_get (m_gst_playbin, "n-text", &n_text, NULL); eDebug("eServiceMP3::async-done - %d video, %d audio, %d subtitle", n_video, n_audio, n_text); if ( n_video + n_audio <= 0 ) stop(); active_idx = 0; m_audioStreams.clear(); m_subtitleStreams.clear(); for (i = 0; i < n_audio; i++) { audioStream audio; gchar *g_codec, *g_lang; GstPad* pad = 0; g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad); GstCaps* caps = gst_pad_get_negotiated_caps(pad); if (!caps) continue; GstStructure* str = gst_caps_get_structure(caps, 0); const gchar *g_type = gst_structure_get_name(str); eDebug("AUDIO STRUCT=%s", g_type); audio.type = gstCheckAudioPad(str); g_codec = g_strdup(g_type); g_lang = g_strdup_printf ("und"); g_signal_emit_by_name (m_gst_playbin, "get-audio-tags", i, &tags); if ( tags && gst_is_tag_list(tags) ) { gst_tag_list_get_string(tags, GST_TAG_AUDIO_CODEC, &g_codec); gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); gst_tag_list_free(tags); } audio.language_code = std::string(g_lang); audio.codec = std::string(g_codec); eDebug("eServiceMP3::audio stream=%i codec=%s language=%s", i, g_codec, g_lang); m_audioStreams.push_back(audio); g_free (g_lang); g_free (g_codec); gst_caps_unref(caps); } for (i = 0; i < n_text; i++) { gchar *g_codec = NULL, *g_lang = NULL; g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); subtitleStream subs; g_lang = g_strdup_printf ("und"); if ( tags && gst_is_tag_list(tags) ) { gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec); gst_tag_list_free(tags); } subs.language_code = std::string(g_lang); eDebug("eServiceMP3::subtitle stream=%i language=%s codec=%s", i, g_lang, g_codec); GstPad* pad = 0; g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); if ( pad ) g_signal_connect (G_OBJECT (pad), "notify::caps", G_CALLBACK (gstTextpadHasCAPS), this); subs.type = getSubtitleType(pad, g_codec); m_subtitleStreams.push_back(subs); g_free (g_lang); } m_event((iPlayableService*)this, evUpdatedInfo); if ( m_errorInfo.missing_codec != "" ) { if ( m_errorInfo.missing_codec.find("video/") == 0 || ( m_errorInfo.missing_codec.find("audio/") == 0 && getNumberOfTracks() == 0 ) ) m_event((iPlayableService*)this, evUser+12); } break; } case GST_MESSAGE_ELEMENT: { if (const GstStructure *msgstruct = gst_message_get_structure(msg)) { if ( gst_is_missing_plugin_message(msg) ) { GstCaps *caps; gst_structure_get (msgstruct, "detail", GST_TYPE_CAPS, &caps, NULL); std::string codec = (const char*) gst_caps_to_string(caps); gchar *description = gst_missing_plugin_message_get_description(msg); if ( description ) { eDebug("eServiceMP3::m_errorInfo.missing_codec = %s", codec.c_str()); m_errorInfo.error_message = "GStreamer plugin " + (std::string)description + " not available!\n"; m_errorInfo.missing_codec = codec.substr(0,(codec.find_first_of(','))); g_free(description); } gst_caps_unref(caps); } else { const gchar *eventname = gst_structure_get_name(msgstruct); if ( eventname ) { if (!strcmp(eventname, "eventSizeChanged") || !strcmp(eventname, "eventSizeAvail")) { gst_structure_get_int (msgstruct, "aspect_ratio", &m_aspect); gst_structure_get_int (msgstruct, "width", &m_width); gst_structure_get_int (msgstruct, "height", &m_height); if (strstr(eventname, "Changed")) m_event((iPlayableService*)this, evVideoSizeChanged); } else if (!strcmp(eventname, "eventFrameRateChanged") || !strcmp(eventname, "eventFrameRateAvail")) { gst_structure_get_int (msgstruct, "frame_rate", &m_framerate); if (strstr(eventname, "Changed")) m_event((iPlayableService*)this, evVideoFramerateChanged); } else if (!strcmp(eventname, "eventProgressiveChanged") || !strcmp(eventname, "eventProgressiveAvail")) { gst_structure_get_int (msgstruct, "progressive", &m_progressive); if (strstr(eventname, "Changed")) m_event((iPlayableService*)this, evVideoProgressiveChanged); } } } } break; } case GST_MESSAGE_BUFFERING: { GstBufferingMode mode; gst_message_parse_buffering(msg, &(m_bufferInfo.bufferPercent)); gst_message_parse_buffering_stats(msg, &mode, &(m_bufferInfo.avgInRate), &(m_bufferInfo.avgOutRate), &(m_bufferInfo.bufferingLeft)); m_event((iPlayableService*)this, evBuffering); break; } case GST_MESSAGE_STREAM_STATUS: { GstStreamStatusType type; GstElement *owner; gst_message_parse_stream_status (msg, &type, &owner); if ( type == GST_STREAM_STATUS_TYPE_CREATE && m_sourceinfo.is_streaming ) { if ( GST_IS_PAD(source) ) owner = gst_pad_get_parent_element(GST_PAD(source)); else if ( GST_IS_ELEMENT(source) ) owner = GST_ELEMENT(source); else owner = 0; if ( owner ) { GstElementFactory *factory = gst_element_get_factory(GST_ELEMENT(owner)); const gchar *name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory)); if (!strcmp(name, "souphttpsrc")) { m_streamingsrc_timeout->start(HTTP_TIMEOUT*1000, true); g_object_set (G_OBJECT (owner), "timeout", HTTP_TIMEOUT, NULL); eDebug("eServiceMP3::GST_STREAM_STATUS_TYPE_CREATE -> setting timeout on %s to %is", name, HTTP_TIMEOUT); } } if ( GST_IS_PAD(source) ) gst_object_unref(owner); } break; } default: break; } g_free (sourceName); }
G_MODULE_EXPORT gboolean live_preview_cb(GstBus *bus, GstMessage *msg, gpointer data) { signal_user_data_t *ud = (signal_user_data_t*)data; switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_UNKNOWN: { //printf("unknown"); } break; case GST_MESSAGE_EOS: { // Done GtkImage *img; //printf("eos"); img = GTK_IMAGE(GHB_WIDGET(ud->builder, "live_preview_play_image")); gtk_image_set_from_icon_name(img, GHB_PLAY_ICON, GTK_ICON_SIZE_BUTTON); gst_element_set_state(ud->preview->play, GST_STATE_PAUSED); ud->preview->pause = TRUE; gst_element_seek(ud->preview->play, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); } break; case GST_MESSAGE_ERROR: { //printf("error\n"); GError *err; gchar *debug; gst_message_parse_error(msg, &err, &debug); g_warning("Gstreamer Error: %s", err->message); g_error_free(err); g_free(debug); } break; case GST_MESSAGE_WARNING: case GST_MESSAGE_INFO: case GST_MESSAGE_TAG: case GST_MESSAGE_BUFFERING: case GST_MESSAGE_STATE_CHANGED: { GstState state, pending; gst_element_get_state(ud->preview->play, &state, &pending, 0); //printf("state change %x\n", state); if (state == GST_STATE_PAUSED || state == GST_STATE_PLAYING) { update_stream_info(ud); } } break; case GST_MESSAGE_STATE_DIRTY: { //printf("state dirty\n"); } break; case GST_MESSAGE_STEP_DONE: { //printf("step done\n"); } break; case GST_MESSAGE_CLOCK_PROVIDE: { //printf("clock provide\n"); } break; case GST_MESSAGE_CLOCK_LOST: { //printf("clock lost\n"); } break; case GST_MESSAGE_NEW_CLOCK: { //printf("new clock\n"); } break; case GST_MESSAGE_STRUCTURE_CHANGE: { //printf("structure change\n"); } break; case GST_MESSAGE_STREAM_STATUS: { //printf("stream status\n"); } break; case GST_MESSAGE_APPLICATION: { //printf("application\n"); } break; case GST_MESSAGE_ELEMENT: { //printf("element\n"); if (gst_is_missing_plugin_message(msg)) { GtkWindow *hb_window; hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window")); gst_element_set_state(ud->preview->play, GST_STATE_PAUSED); gchar *message, *desc; desc = gst_missing_plugin_message_get_description(msg); message = g_strdup_printf( _("Missing GStreamer plugin\n" "Audio or Video may not play as expected\n\n%s"), desc); ghb_message_dialog(hb_window, GTK_MESSAGE_WARNING, message, "Ok", NULL); g_free(message); gst_element_set_state(ud->preview->play, GST_STATE_PLAYING); } } break; case GST_MESSAGE_SEGMENT_START: { //printf("segment start\n"); } break; case GST_MESSAGE_SEGMENT_DONE: { //printf("segment done\n"); } break; #if GST_CHECK_VERSION(1, 0, 0) case GST_MESSAGE_DURATION_CHANGED: { //printf("duration change\n"); }; #endif case GST_MESSAGE_LATENCY: { //printf("latency\n"); }; case GST_MESSAGE_ASYNC_START: { //printf("async start\n"); } break; case GST_MESSAGE_ASYNC_DONE: { //printf("async done\n"); } break; case GST_MESSAGE_REQUEST_STATE: { //printf("request state\n"); } break; case GST_MESSAGE_STEP_START: { //printf("step start\n"); } break; case GST_MESSAGE_QOS: { //printf("qos\n"); } break; #if GST_CHECK_VERSION(1, 0, 0) case GST_MESSAGE_PROGRESS: { //printf("progress\n"); } break; case GST_MESSAGE_TOC: { //printf("toc\n"); } break; case GST_MESSAGE_RESET_TIME: { //printf("reset time\n"); } break; case GST_MESSAGE_STREAM_START: { //printf("stream start\n"); }; #endif case GST_MESSAGE_ANY: { //printf("any\n"); } break; default: { // Ignore //printf("?msg? %x\n", GST_MESSAGE_TYPE(msg)); } } return TRUE; }
gboolean check_missing_plugins(GstEncodingProfile *profile, char ***details, char ***descriptions) { GstElement *encodebin; GstBus *bus; GstPad *pad; gboolean ret; ret = FALSE; encodebin = gst_element_factory_make("encodebin", NULL); if (encodebin == NULL) { g_warning("Unable to create encodebin"); return TRUE; } bus = gst_bus_new(); gst_element_set_bus(encodebin, bus); gst_bus_set_flushing(bus, FALSE); /* necessary? */ g_object_set(encodebin, "profile", profile, NULL); pad = gst_element_get_static_pad(encodebin, "audio_0"); if (pad == NULL) { GstMessage *message; GList *messages = NULL; GList *m; message = gst_bus_pop(bus); while (message != NULL) { if (gst_is_missing_plugin_message(message)) messages = g_list_append(messages, message); else gst_message_unref(message); message = gst_bus_pop(bus); } if (messages != NULL) { int i; if (details != NULL) *details = g_new0(char *, g_list_length(messages)+1); if (descriptions != NULL) *descriptions = g_new0(char *, g_list_length(messages)+1); i = 0; for (m = messages; m != NULL; m = m->next) { char *str; if (details != NULL) { str = gst_missing_plugin_message_get_installer_detail(m->data); (*details)[i] = str; } if (descriptions != NULL) { str = gst_missing_plugin_message_get_description(m->data); (*descriptions)[i] = str; } i++; } ret = TRUE; g_list_foreach(messages,(GFunc)gst_message_unref, NULL); g_list_free(messages); }