Exemple #1
0
static void
process_tag (const GstTagList *list, const gchar *tag, RBPlayerGst *player)
{
	RBMetaDataField field;
	GValue value = {0,};

	/* process embedded images */
	if (!g_strcmp0 (tag, GST_TAG_IMAGE) || !g_strcmp0 (tag, GST_TAG_PREVIEW_IMAGE)) {
		GdkPixbuf *pixbuf;
		pixbuf = rb_gst_process_embedded_image (list, tag);
		if (pixbuf != NULL) {
			_rb_player_emit_image (RB_PLAYER (player),
					       player->priv->stream_data,
					       pixbuf);
			g_object_unref (pixbuf);
		}
	} else if (rb_gst_process_tag_string (list, tag, &field, &value)) {
		rb_debug ("emitting info field %d", field);
		_rb_player_emit_info (RB_PLAYER (player),
				      player->priv->stream_data,
				      field,
				      &value);
		g_value_unset (&value);
	}
}
Exemple #2
0
static gboolean
tick_timeout (RBPlayerGst *mp)
{
	if (mp->priv->playing) {
		_rb_player_emit_tick (RB_PLAYER (mp),
				      mp->priv->stream_data,
				      rb_player_get_time (RB_PLAYER (mp)),
				      -1);
	}
	return TRUE;
}
Exemple #3
0
static void
emit_playing_stream_and_tags (RBPlayerGst *player, gboolean track_change)
{
	GList *t;

	if (track_change) {
		/* swap stream data */
		_destroy_stream_data (player);
		player->priv->stream_data = player->priv->next_stream_data;
		player->priv->stream_data_destroy = player->priv->next_stream_data_destroy;
		player->priv->next_stream_data = NULL;
		player->priv->next_stream_data_destroy = NULL;
	}

	_rb_player_emit_playing_stream (RB_PLAYER (player), player->priv->stream_data);

	/* process any tag lists we received while starting the stream */
	for (t = player->priv->stream_tags; t != NULL; t = t->next) {
		GstTagList *tags;

		tags = (GstTagList *)t->data;
		rb_debug ("processing buffered taglist");
		gst_tag_list_foreach (tags, (GstTagForeachFunc) process_tag, player);
		gst_tag_list_free (tags);
	}
	g_list_free (player->priv->stream_tags);
	player->priv->stream_tags = NULL;
}
Exemple #4
0
static gboolean
about_to_finish_idle (RBPlayerGst *player)
{
	_rb_player_emit_eos (RB_PLAYER (player), player->priv->stream_data, TRUE);

	g_mutex_lock (&player->priv->eos_lock);
	g_cond_signal (&player->priv->eos_cond);
	g_mutex_unlock (&player->priv->eos_lock);
	return FALSE;
}
Exemple #5
0
static gboolean
impl_add_filter (RBPlayerGstFilter *player, GstElement *element)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	if (mp->priv->filterbin == NULL) {
		mp->priv->waiting_filters = g_list_prepend (mp->priv->waiting_filters, element);
		return TRUE;
	}
	return rb_gst_add_filter (RB_PLAYER (mp), mp->priv->filterbin, element, need_pad_blocking (mp));
}
Exemple #6
0
static gboolean
impl_add_tee (RBPlayerGstTee *player, GstElement *element)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	if (mp->priv->tee == NULL) {
		mp->priv->waiting_tees = g_list_prepend (mp->priv->waiting_tees, element);
		return TRUE;
	}

	return rb_gst_add_tee (RB_PLAYER (player), mp->priv->tee, element, need_pad_blocking (mp));
}
Exemple #7
0
static gboolean
impl_remove_tee (RBPlayerGstTee *player, GstElement *element)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	if (mp->priv->tee == NULL) {
		gst_object_sink (element);
		mp->priv->waiting_tees = g_list_remove (mp->priv->waiting_tees, element);
		return TRUE;
	}

	return rb_gst_remove_tee (RB_PLAYER (mp), mp->priv->tee, element, need_pad_blocking (mp));
}
Exemple #8
0
static gboolean
impl_remove_filter (RBPlayerGstFilter *player, GstElement *element)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	if (mp->priv->filterbin == NULL) {
		gst_object_sink (element);
		mp->priv->waiting_filters = g_list_remove (mp->priv->waiting_filters, element);
		return TRUE;
	}

	return rb_gst_remove_filter (RB_PLAYER (mp), mp->priv->filterbin, element, need_pad_blocking (mp));
}
Exemple #9
0
static gboolean
tick_timeout (RBPlayerGst *mp)
{
	if (mp->priv->playing) {
		gint64 position;

		position = rb_player_get_time (RB_PLAYER (mp));

		/* if we don't have stream-changed messages, do the track change when
		 * the playback position is less than one second into the current track,
		 * which pretty much has to be the new one.
		 */
		if (mp->priv->playbin_stream_changing && (position < GST_SECOND)) {
			emit_playing_stream_and_tags (mp, TRUE);
			mp->priv->playbin_stream_changing = FALSE;
		}

		_rb_player_emit_tick (RB_PLAYER (mp),
				      mp->priv->stream_data,
				      position,
				      -1);
	}
	return TRUE;
}
static gboolean
emit_volume_changed_idle (RBPlayerGst *player)
{
	double vol;

	if (gst_element_implements_interface (player->priv->playbin, GST_TYPE_STREAM_VOLUME)) {
		vol = gst_stream_volume_get_volume (GST_STREAM_VOLUME (player->priv->playbin),
						    GST_STREAM_VOLUME_FORMAT_CUBIC);
	} else {
		vol = player->priv->cur_volume;
	}

	_rb_player_emit_volume_changed (RB_PLAYER (player), vol);
	return FALSE;
}
Exemple #11
0
static void
about_to_finish_cb (GstElement *playbin, RBPlayerGst *player)
{
	if (player->priv->stream_change_pending == TRUE) {
		/* this probably shouldn't happen, but it's OK if it does, I think */
		rb_debug ("got about-to-finish, but we already have a stream change pending.");
		return;
	}

	/* don't handle about-to-finish for cdda */
	if (g_str_has_prefix (player->priv->uri, "cdda://")) {
		rb_debug ("ignoring about-to-finish for %s", player->priv->uri);
		return;
	}

	/* emit EOS now and hope we get something to play */
	player->priv->current_track_finishing = TRUE;

	_rb_player_emit_eos (RB_PLAYER (player), player->priv->stream_data, TRUE);
}
Exemple #12
0
static gboolean
actually_emit_stream_and_tags (RBPlayerGst *player)
{
	GList *t;

	_rb_player_emit_playing_stream (RB_PLAYER (player), player->priv->stream_data);

	/* process any tag lists we received while starting the stream */
	for (t = player->priv->stream_tags; t != NULL; t = t->next) {
		GstTagList *tags;

		tags = (GstTagList *)t->data;
		rb_debug ("processing buffered taglist");
		gst_tag_list_foreach (tags, (GstTagForeachFunc) process_tag, player);
		gst_tag_list_free (tags);
	}
	g_list_free (player->priv->stream_tags);
	player->priv->stream_tags = NULL;

	player->priv->emit_stream_idle_id = 0;
	return FALSE;
}
Exemple #13
0
static gboolean
bus_cb (GstBus *bus, GstMessage *message, RBPlayerGst *mp)
{
	const GstStructure *structure;
	g_return_val_if_fail (mp != NULL, FALSE);

	switch (GST_MESSAGE_TYPE (message)) {
	case GST_MESSAGE_ERROR: {
		char *debug;
		GError *error = NULL;
		GError *sig_error = NULL;
		int code;
		gboolean emit = TRUE;

		gst_message_parse_error (message, &error, &debug);

		/* If we've already got an error, ignore 'internal data flow error'
		 * type messages, as they're too generic to be helpful.
		 */
		if (mp->priv->emitted_error &&
		    error->domain == GST_STREAM_ERROR &&
		    error->code == GST_STREAM_ERROR_FAILED) {
			rb_debug ("Ignoring generic error \"%s\"", error->message);
			emit = FALSE;
		}

		code = rb_gst_error_get_error_code (error);

		if (emit) {
			if (message_from_sink (mp->priv->audio_sink, message)) {
				rb_debug ("got error from sink: %s (%s)", error->message, debug);
				/* Translators: the parameter here is an error message */
				g_set_error (&sig_error,
					     RB_PLAYER_ERROR,
					     code,
					     _("Failed to open output device: %s"),
					     error->message);
			} else {
				rb_debug ("got error from stream: %s (%s)", error->message, debug);
				g_set_error (&sig_error,
					     RB_PLAYER_ERROR,
					     code,
					     "%s",
					     error->message);
			}
			state_change_finished (mp, sig_error);
			mp->priv->emitted_error = TRUE;
			_rb_player_emit_error (RB_PLAYER (mp), mp->priv->stream_data, sig_error);
		}

		/* close if not already closing */
		if (mp->priv->uri != NULL)
			rb_player_close (RB_PLAYER (mp), NULL, NULL);

		g_error_free (error);
		g_free (debug);
		break;
	}

	case GST_MESSAGE_EOS:
		_rb_player_emit_eos (RB_PLAYER (mp), mp->priv->stream_data, FALSE);
		break;

	case GST_MESSAGE_STATE_CHANGED:
		{
			GstState oldstate;
			GstState newstate;
			GstState pending;
			gst_message_parse_state_changed (message, &oldstate, &newstate, &pending);
			if (GST_MESSAGE_SRC (message) == GST_OBJECT (mp->priv->playbin)) {
				rb_debug ("playbin reached state %s", gst_element_state_get_name (newstate));
				if (pending == GST_STATE_VOID_PENDING) {
					state_change_finished (mp, NULL);
				}
			}
			break;
		}

	case GST_MESSAGE_TAG: {
		GstTagList *tags;
		gst_message_parse_tag (message, &tags);

		if (mp->priv->stream_change_pending || mp->priv->playbin_stream_changing) {
			mp->priv->stream_tags = g_list_append (mp->priv->stream_tags, tags);
		} else {
			gst_tag_list_foreach (tags, (GstTagForeachFunc) process_tag, mp);
			gst_tag_list_free (tags);
		}
		break;
	}


	case GST_MESSAGE_BUFFERING: {
		gint progress;

		structure = gst_message_get_structure (message);
		if (!gst_structure_get_int (structure, "buffer-percent", &progress)) {
			g_warning ("Could not get value from BUFFERING message");
			break;
		}
		if (progress >= 100) {
			mp->priv->buffering = FALSE;
			if (mp->priv->playing) {
				rb_debug ("buffering done, setting pipeline back to PLAYING");
				gst_element_set_state (mp->priv->playbin, GST_STATE_PLAYING);
			} else {
				rb_debug ("buffering done, leaving pipeline PAUSED");
			}
		} else if (mp->priv->buffering == FALSE && mp->priv->playing) {
			GstState cur_state;

			gst_element_get_state (mp->priv->playbin, &cur_state, NULL, 0);
			if (cur_state == GST_STATE_PLAYING) {
				rb_debug ("buffering - temporarily pausing playback");
				gst_element_set_state (mp->priv->playbin, GST_STATE_PAUSED);
			} else {
				rb_debug ("buffering - during preroll; doing nothing");
			}
			mp->priv->buffering = TRUE;
		}

		_rb_player_emit_buffering (RB_PLAYER (mp), mp->priv->stream_data, progress);
		break;
	}

	case GST_MESSAGE_APPLICATION:
		structure = gst_message_get_structure (message);
		_rb_player_emit_event (RB_PLAYER (mp), mp->priv->stream_data, gst_structure_get_name (structure), NULL);
		break;

	case GST_MESSAGE_ELEMENT:
		structure = gst_message_get_structure (message);
		if (gst_is_missing_plugin_message (message)) {
			handle_missing_plugin_message (mp, message);
		} else if (mp->priv->playbin_stream_changing &&
			   gst_structure_has_name (structure, "playbin2-stream-changed")) {
			rb_debug ("got playbin2-stream-changed message");
			mp->priv->playbin_stream_changing = FALSE;
			emit_playing_stream_and_tags (mp, TRUE);
		} else if (gst_structure_has_name (structure, "redirect")) {
			const char *uri = gst_structure_get_string (structure, "new-location");
			_rb_player_emit_redirect (RB_PLAYER (mp), mp->priv->stream_data, uri);
		}
		break;

	default:
		break;
	}

	/* emit message signals too, so plugins can process messages */
	gst_bus_async_signal_func (bus, message, NULL);

	return TRUE;
}
Exemple #14
0
RBPlayer *
rb_player_gst_new (GError **error)
{
	return RB_PLAYER (g_object_new (RB_TYPE_PLAYER_GST, NULL, NULL));
}