Exemplo n.º 1
0
static void
stop_visualizer_cb (RBVisualizerPage *page, RBVisualizerPlugin *plugin)
{
	if (plugin->visualizer == NULL) {
		return;
	}

	if (plugin->playbin_notify_id) {
		int playbin_flags;

		g_object_get (plugin->playbin, "flags", &playbin_flags, NULL);
		playbin_flags &= ~PLAYBIN2_FLAG_VIS;
		rb_debug ("disabling vis; new playbin2 flags %d", playbin_flags);
		g_object_set (plugin->playbin,
			      "flags", playbin_flags,
			      "vis-plugin", NULL,
			      NULL);
	} else {
		rb_debug ("removing visualizer bin from pipeline");
		rb_player_gst_tee_remove_tee (RB_PLAYER_GST_TEE (plugin->player),
					      plugin->visualizer);
	}

	if (plugin->visualizer) {
		g_object_unref (plugin->visualizer);
		plugin->visualizer = NULL;
	}
}
static void
really_remove_tee (GstPad *pad, gboolean blocked, RBGstPipelineOp *op)
{
	GstElement *bin;
	GstElement *parent;

	rb_debug ("really removing tee %p", op->element);

	_rb_player_gst_tee_emit_tee_pre_remove (RB_PLAYER_GST_TEE (op->player), op->element);

	/* find bin, remove everything */
	bin = GST_ELEMENT_PARENT (op->element);
	g_object_ref (bin);

	parent = GST_ELEMENT_PARENT (bin);
	gst_bin_remove (GST_BIN (parent), bin);

	gst_element_set_state (bin, GST_STATE_NULL);
	gst_bin_remove (GST_BIN (bin), op->element);
	g_object_unref (bin);

	/* if we're supposed to be playing, unblock the sink */
	if (blocked) {
		rb_debug ("unblocking pad after removing tee");
		gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback)pipeline_op_done, NULL);
	}

	free_pipeline_op (op);
}
static void
really_add_tee (GstPad *pad, gboolean blocked, RBGstPipelineOp *op)
{
	GstElement *queue;
	GstElement *audioconvert;
	GstElement *bin;
	GstElement *parent_bin;
	GstPad *sinkpad;
	GstPad *ghostpad;

	rb_debug ("really adding tee %p", op->element);

	/* set up containing bin */
	bin = gst_bin_new (NULL);
	queue = gst_element_factory_make ("queue", NULL);
	audioconvert = gst_element_factory_make ("audioconvert", NULL);

	/* The bin contains elements that change state asynchronously
	 * and not as part of a state change in the entire pipeline.
	 */
	g_object_set (bin, "async-handling", TRUE, NULL);

	g_object_set (queue, "max-size-buffers", 3, NULL);

	gst_bin_add_many (GST_BIN (bin), queue, audioconvert, op->element, NULL);
	gst_element_link_many (queue, audioconvert, op->element, NULL);

	/* add ghost pad */
	sinkpad = gst_element_get_static_pad (queue, "sink");
	ghostpad = gst_ghost_pad_new ("sink", sinkpad);
	gst_element_add_pad (bin, ghostpad);
	gst_object_unref (sinkpad);

	/* add it into the pipeline */
	parent_bin = GST_ELEMENT_PARENT (op->fixture);
	gst_bin_add (GST_BIN (parent_bin), bin);
	gst_element_link (op->fixture, bin);

	/* if we're supposed to be playing, unblock the sink */
	if (blocked) {
		rb_debug ("unblocking pad after adding tee");

		gst_element_set_state (parent_bin, GST_STATE_PLAYING);
		gst_object_ref (ghostpad);
		gst_pad_set_blocked_async (pad,
					   FALSE,
					   (GstPadBlockCallback)pipeline_op_done,
					   ghostpad);
	} else {
		gst_element_set_state (bin, GST_STATE_PAUSED);
		gst_object_ref (ghostpad);
		pipeline_op_done (NULL, FALSE, ghostpad);
	}

	_rb_player_gst_tee_emit_tee_inserted (RB_PLAYER_GST_TEE (op->player), op->element);

	free_pipeline_op (op);
}
Exemplo n.º 4
0
static void
start_visualizer_cb (RBVisualizerPage *page, RBVisualizerPlugin *plugin)
{
	GstPad *pad;
	char *plugin_name;

	if (plugin->visualizer) {
		g_object_unref (plugin->visualizer);
		plugin->visualizer = NULL;
		plugin->identity = NULL;
		plugin->capsfilter = NULL;
		plugin->vis_plugin = NULL;
	}
	plugin->visualizer = gst_bin_new (NULL);

	/* create common bits of visualizer bin: identity ! <effect> ! capsfilter */
	plugin->identity = gst_element_factory_make ("identity", NULL);
	plugin->capsfilter = gst_element_factory_make ("capsfilter", NULL);

	plugin_name = g_settings_get_string (plugin->settings, "vis-plugin");
	if (plugin_name != NULL) {
		plugin->vis_plugin = gst_element_factory_make (plugin_name, NULL);
		if (plugin->vis_plugin == NULL) {
			g_warning ("Configured visualizer plugin %s not available", plugin_name);
		}
		g_free (plugin_name);
	}
	if (plugin->vis_plugin == NULL) {
		plugin->vis_plugin = gst_element_factory_make ("goom", NULL);
		if (plugin->vis_plugin == NULL) {
			g_warning ("Fallback visualizer plugin (goom) not available");
			return;
		}
	}

	/* set up capsfilter */
	gst_bin_add_many (GST_BIN (plugin->visualizer), plugin->identity, plugin->vis_plugin, plugin->capsfilter, NULL);

	pad = gst_element_get_static_pad (plugin->identity, "sink");
	gst_element_add_pad (plugin->visualizer, gst_ghost_pad_new ("sink", pad));
	gst_object_unref (pad);

	/* XXX check errors etc. */
	if (gst_element_link_many (plugin->identity, plugin->vis_plugin, plugin->capsfilter, NULL) == FALSE) {
		g_warning ("couldn't link visualizer bin elements");
		return;
	}
	fixate_vis_caps (plugin);

	g_object_ref (plugin->visualizer);

	if (plugin->playbin_notify_id) {
		GstPad *pad;
		int playbin_flags;

		pad = gst_element_get_static_pad (plugin->capsfilter, "src");
		gst_element_add_pad (plugin->visualizer, gst_ghost_pad_new ("src", pad));
		gst_object_unref (pad);

		g_object_get (plugin->playbin, "flags", &playbin_flags, NULL);
		if (plugin->playbin != NULL) {
			playbin_flags |= PLAYBIN2_FLAG_VIS;
			rb_debug ("enabling vis; new playbin2 flags %x", playbin_flags);
			g_object_set (plugin->playbin,
				      "vis-plugin", plugin->visualizer,
				      "flags", playbin_flags,
				      NULL);
		} else {
			rb_debug ("playback hasn't started yet");
		}
	} else {
		GstElement *colorspace;
		GstElement *queue;

		colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
		queue = gst_element_factory_make ("queue", NULL);

		g_object_set (queue, "max-size-buffers", 3, "max-size-bytes", 0, "max-size-time", (gint64) 0, NULL);

		gst_bin_add_many (GST_BIN (plugin->visualizer), queue, colorspace, plugin->sink, NULL);
		gst_element_link_many (plugin->capsfilter, queue, colorspace, plugin->sink, NULL);

		rb_debug ("adding visualizer bin to the pipeline");
		rb_player_gst_tee_add_tee (RB_PLAYER_GST_TEE (plugin->player),
					   plugin->visualizer);
	}
}
Exemplo n.º 5
0
static gboolean
construct_pipeline (RBPlayerGst *mp, GError **error)
{
	GstElement *sink;

	mp->priv->playbin = gst_element_factory_make ("playbin2", NULL);
	if (mp->priv->playbin == NULL) {
		g_set_error (error,
			     RB_PLAYER_ERROR,
			     RB_PLAYER_ERROR_GENERAL,
			     _("Failed to create playbin2 element; check your GStreamer installation"));
		return FALSE;
	}
	g_signal_connect_object (G_OBJECT (mp->priv->playbin),
				 "about-to-finish",
				 G_CALLBACK (about_to_finish_cb),
				 mp, 0);
	g_signal_connect_object (G_OBJECT (mp->priv->playbin),
				 "deep-notify::volume",
				 G_CALLBACK (volume_notify_cb),
				 mp, 0);
	g_signal_connect_object (G_OBJECT (mp->priv->playbin),
				 "notify::source",
				 G_CALLBACK (source_notify_cb),
				 mp, 0);

	gst_bus_add_watch (gst_element_get_bus (mp->priv->playbin),
			   (GstBusFunc) bus_cb,
			   mp);

	/* let plugins add bits to playbin */
	g_object_notify (G_OBJECT (mp), "playbin");
	g_object_notify (G_OBJECT (mp), "bus");

	/* Use gsettingsaudiosink for audio if there's no audio sink yet */
	g_object_get (mp->priv->playbin, "audio-sink", &mp->priv->audio_sink, NULL);
	if (mp->priv->audio_sink == NULL) {
		const char *try_sinks[] = { "gsettingsaudiosink", "gconfaudiosink", "autoaudiosink" };
		int i;

		for (i = 0; i < G_N_ELEMENTS (try_sinks); i++) {
			mp->priv->audio_sink = rb_player_gst_try_audio_sink (try_sinks[i], NULL);
			if (mp->priv->audio_sink != NULL) {
				g_object_set (mp->priv->playbin, "audio-sink", mp->priv->audio_sink, NULL);
				break;
			}
		}
	} else {
		rb_debug ("existing audio sink found");
		g_object_unref (mp->priv->audio_sink);
	}

	{
		GstPad *pad;
		GList *l;
		GstElement *queue;
		GstPad *ghostpad;

		/* setup filterbin */
		mp->priv->filterbin = rb_gst_create_filter_bin ();

		/* set up the sinkbin with its tee element */
		mp->priv->sinkbin = gst_bin_new (NULL);
		mp->priv->tee = gst_element_factory_make ("tee", NULL);
		queue = gst_element_factory_make ("queue", NULL);

		/* link it all together and insert */
		gst_bin_add_many (GST_BIN (mp->priv->sinkbin), mp->priv->filterbin, mp->priv->tee, queue, mp->priv->audio_sink, NULL);
		gst_element_link_many (mp->priv->filterbin, mp->priv->tee, queue, mp->priv->audio_sink, NULL);

		pad = gst_element_get_pad (mp->priv->filterbin, "sink");
		ghostpad = gst_ghost_pad_new ("sink", pad);
		gst_element_add_pad (mp->priv->sinkbin, ghostpad);
		gst_object_unref (pad);

		g_object_set (G_OBJECT (mp->priv->playbin), "audio-sink", mp->priv->sinkbin, NULL);

		/* add any tees and filters that were waiting for us */
		for (l = mp->priv->waiting_tees; l != NULL; l = g_list_next (l)) {
			rb_player_gst_tee_add_tee (RB_PLAYER_GST_TEE (mp), GST_ELEMENT (l->data));
		}
		g_list_free (mp->priv->waiting_tees);
		mp->priv->waiting_tees = NULL;

		for (l = mp->priv->waiting_filters; l != NULL; l = g_list_next (l)) {
			rb_player_gst_filter_add_filter (RB_PLAYER_GST_FILTER(mp), GST_ELEMENT (l->data));
		}
		g_list_free (mp->priv->waiting_filters);
		mp->priv->waiting_filters = NULL;
	}

	/* Use fakesink for video if there's no video sink yet */
	g_object_get (mp->priv->playbin, "video-sink", &sink, NULL);
	if (sink == NULL) {
		sink = gst_element_factory_make ("fakesink", NULL);
		g_object_set (mp->priv->playbin, "video-sink", sink, NULL);
	} else {
		g_object_unref (sink);
	}

	if (mp->priv->cur_volume > 1.0)
		mp->priv->cur_volume = 1.0;
	if (mp->priv->cur_volume < 0.0)
		mp->priv->cur_volume = 0;

	rb_debug ("pipeline construction complete");
	return TRUE;
}