예제 #1
0
static gboolean
impl_open (RBPlayer *player,
	   const char *uri,
	   gpointer stream_data,
	   GDestroyNotify stream_data_destroy,
	   GError **error)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	if (mp->priv->playbin == NULL) {
		if (!construct_pipeline (mp, error))
			return FALSE;
	}

	g_assert (mp->priv->playbin != NULL);

	if (uri == NULL) {
		return impl_close (player, NULL, error);
	}

	rb_debug ("setting new uri to %s", uri);
	_destroy_next_stream_data (mp);
	g_free (mp->priv->prev_uri);
	mp->priv->prev_uri = mp->priv->uri;
	mp->priv->uri = g_strdup (uri);
	mp->priv->next_stream_data = stream_data;
	mp->priv->next_stream_data_destroy = stream_data_destroy;
	mp->priv->emitted_error = FALSE;
	mp->priv->stream_change_pending = TRUE;

	return TRUE;
}
예제 #2
0
static float
impl_get_volume (RBPlayer *player)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	return mp->priv->cur_volume;
}
예제 #3
0
static gboolean
impl_playing (RBPlayer *player)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	return mp->priv->playing;
}
예제 #4
0
static gboolean
impl_opened (RBPlayer *player)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	return mp->priv->uri != NULL;
}
예제 #5
0
static void
impl_dispose (GObject *object)
{
	RBPlayerGst *mp;

	mp = RB_PLAYER_GST (object);

	if (mp->priv->tick_timeout_id != 0) {
		g_source_remove (mp->priv->tick_timeout_id);
		mp->priv->tick_timeout_id = 0;
	}

	if (mp->priv->playbin != NULL) {
		gst_element_set_state (mp->priv->playbin, GST_STATE_NULL);
		g_object_unref (mp->priv->playbin);
		mp->priv->playbin = NULL;
		mp->priv->audio_sink = NULL;
	}

	if (mp->priv->waiting_tees != NULL) {
		g_list_foreach (mp->priv->waiting_tees, (GFunc)gst_object_sink, NULL);
		g_list_free (mp->priv->waiting_tees);
		mp->priv->waiting_tees = NULL;
	}

	if (mp->priv->waiting_filters != NULL) {
		g_list_foreach (mp->priv->waiting_filters, (GFunc)gst_object_sink, NULL);
		g_list_free (mp->priv->waiting_filters);
		mp->priv->waiting_filters = NULL;
	}

	G_OBJECT_CLASS (rb_player_gst_parent_class)->dispose (object);
}
예제 #6
0
static gboolean
impl_close (RBPlayer *player, const char *uri, GError **error)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	if ((uri != NULL) && (mp->priv->uri != NULL) && strcmp (mp->priv->uri, uri) == 0) {
		rb_debug ("URI doesn't match current playing URI; ignoring");
		return TRUE;
	}

	mp->priv->playing = FALSE;
	mp->priv->buffering = FALSE;
	mp->priv->current_track_finishing = FALSE;

	_destroy_stream_data (mp);
	if (uri == NULL) {
		_destroy_next_stream_data (mp);
	}
	g_free (mp->priv->uri);
	g_free (mp->priv->prev_uri);
	mp->priv->uri = NULL;
	mp->priv->prev_uri = NULL;

	if (mp->priv->tick_timeout_id != 0) {
		g_source_remove (mp->priv->tick_timeout_id);
		mp->priv->tick_timeout_id = 0;
	}

	if (mp->priv->playbin != NULL) {
		start_state_change (mp, GST_STATE_NULL, PLAYER_SHUTDOWN);
	}
	return TRUE;
}
예제 #7
0
static void
impl_get_property (GObject *object,
		   guint prop_id,
		   GValue *value,
		   GParamSpec *pspec)
{
	RBPlayerGst *mp = RB_PLAYER_GST (object);

	switch (prop_id) {
	case PROP_PLAYBIN:
		g_value_set_object (value, mp->priv->playbin);
		break;
	case PROP_BUS:
		if (mp->priv->playbin) {
			GstBus *bus;
			bus = gst_element_get_bus (mp->priv->playbin);
			g_value_set_object (value, bus);
			gst_object_unref (bus);
		}
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
예제 #8
0
static gboolean
impl_play (RBPlayer *player, RBPlayerPlayType play_type, gint64 crossfade, GError **error)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	g_return_val_if_fail (mp->priv->playbin != NULL, FALSE);

	mp->priv->track_change = TRUE;

	if (mp->priv->stream_change_pending == FALSE) {
		rb_debug ("no stream change pending, just restarting playback");
		mp->priv->track_change = FALSE;
		start_state_change (mp, GST_STATE_PLAYING, FINISH_TRACK_CHANGE);
	} else if (mp->priv->current_track_finishing) {
		switch (play_type) {
		case RB_PLAYER_PLAY_AFTER_EOS:
			rb_debug ("current track finishing -> just setting URI on playbin");
			g_object_set (mp->priv->playbin, "uri", mp->priv->uri, NULL);
			mp->priv->playbin_stream_changing = TRUE;
			track_change_done (mp, NULL);
			break;

		case RB_PLAYER_PLAY_REPLACE:
		case RB_PLAYER_PLAY_CROSSFADE:
			rb_debug ("current track finishing, waiting for EOS to start next");
			break;

		default:
			g_assert_not_reached ();
		}
	} else {
		gboolean reused = FALSE;

		/* try to reuse the stream */
		if (mp->priv->prev_uri != NULL) {
			g_signal_emit (mp,
				       signals[CAN_REUSE_STREAM], 0,
				       mp->priv->uri, mp->priv->prev_uri, mp->priv->playbin,
				       &reused);

			if (reused) {
				rb_debug ("reusing stream to switch from %s to %s", mp->priv->prev_uri, mp->priv->uri);
				g_signal_emit (player,
					       signals[REUSE_STREAM], 0,
					       mp->priv->uri, mp->priv->prev_uri, mp->priv->playbin);
				track_change_done (mp, *error);
			}
		}

		/* no stream reuse, so stop, set the new URI, then start */
		if (reused == FALSE) {
			rb_debug ("not in transition, stopping current track to start the new one");
			start_state_change (mp, GST_STATE_READY, SET_NEXT_URI);
		}

	}

	return TRUE;
}
예제 #9
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));
}
예제 #10
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));
}
예제 #11
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));
}
예제 #12
0
static void
impl_set_time (RBPlayer *player, gint64 time)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	rb_debug ("seeking to %" G_GINT64_FORMAT, time);
	gst_element_seek (mp->priv->playbin, 1.0,
			  GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
			  GST_SEEK_TYPE_SET, time,
			  GST_SEEK_TYPE_NONE, -1);

	gst_element_get_state (mp->priv->playbin, NULL, NULL, 100 * GST_MSECOND);
}
예제 #13
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));
}
예제 #14
0
static void
impl_pause (RBPlayer *player)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	if (!mp->priv->playing)
		return;

	mp->priv->playing = FALSE;

	g_return_if_fail (mp->priv->playbin != NULL);

	start_state_change (mp, GST_STATE_PAUSED, STOP_TICK_TIMER);
}
예제 #15
0
static gint64
impl_get_time (RBPlayer *player)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);

	if (mp->priv->playbin != NULL) {
		gint64 position = -1;
		GstFormat fmt = GST_FORMAT_TIME;

		gst_element_query_position (mp->priv->playbin, &fmt, &position);
		return position;
	} else {
		return -1;
	}
}
예제 #16
0
static void
impl_set_volume (RBPlayer *player,
		 float volume)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);
	g_return_if_fail (volume >= 0.0 && volume <= 1.0);

	mp->priv->volume_changed++;
	if (mp->priv->volume_applied > 0) {
		set_playbin_volume (mp, volume);
		mp->priv->volume_applied = mp->priv->volume_changed;
	} else {
		/* volume will be applied in the first call to impl_play */
	}

	mp->priv->cur_volume = volume;
}
예제 #17
0
static void
impl_set_property (GObject *object,
		   guint prop_id,
		   const GValue *value,
		   GParamSpec *pspec)
{
	RBPlayerGst *mp = RB_PLAYER_GST (object);

	switch (prop_id) {
	case PROP_BUFFER_SIZE:
		mp->priv->buffer_size = g_value_get_uint (value);
		if (mp->priv->playbin != NULL) {
			rb_debug ("setting buffer size on playbin: %d", mp->priv->buffer_size * 1024);
			g_object_set (mp->priv->playbin, "buffer-size", mp->priv->buffer_size * 1024, NULL);
		}
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
예제 #18
0
static gboolean
impl_seekable (RBPlayer *player)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);
	gboolean can_seek = TRUE;
	GstQuery *query;

	if (mp->priv->playbin == NULL)
		return FALSE;

	query = gst_query_new_seeking (GST_FORMAT_TIME);
	if (gst_element_query (mp->priv->playbin, query)) {
		gst_query_parse_seeking (query, NULL, &can_seek, NULL, NULL);
	} else {
		gst_query_unref (query);

		query = gst_query_new_duration (GST_FORMAT_TIME);
		can_seek = gst_element_query (mp->priv->playbin, query);
	}
	gst_query_unref (query);

	return can_seek;
}