[the-board/sound-thing] more player (duration and progress)
- From: Lucas Rocha <lucasr src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [the-board/sound-thing] more player (duration and progress)
- Date: Wed, 5 Jan 2011 16:18:52 +0000 (UTC)
commit 8464d78a288db2b170f745d79c92762e5f827ec2
Author: Lucas Rocha <lucasr gnome org>
Date: Wed Jan 5 16:06:49 2011 +0000
more player (duration and progress)
src/tb/tb-sound-player.c | 296 +++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 281 insertions(+), 15 deletions(-)
---
diff --git a/src/tb/tb-sound-player.c b/src/tb/tb-sound-player.c
index c89761c..9103576 100644
--- a/src/tb/tb-sound-player.c
+++ b/src/tb/tb-sound-player.c
@@ -10,12 +10,16 @@ G_DEFINE_TYPE (TbSoundPlayer, tb_sound_player, G_TYPE_OBJECT);
#define TB_SOUND_PLAYER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), TB_TYPE_SOUND_PLAYER, TbSoundPlayerPrivate))
+#define TICK_TIMEOUT 0.5
+
enum
{
PROP_0,
PROP_PLAYING,
PROP_STATE,
+ PROP_PROGRESS,
+ PROP_DURATION,
PROP_FILENAME
};
@@ -26,6 +30,13 @@ struct _TbSoundPlayerPrivate
TbSoundPlayerState state;
char *filename;
gboolean playing;
+ GstState stacked_state;
+ gdouble stacked_progress;
+ gdouble target_progress;
+ gdouble duration;
+ guint tick_timeout_id;
+
+ guint in_seek : 1;
};
static void tb_sound_player_destroy_pipeline (TbSoundPlayer *player);
@@ -50,7 +61,7 @@ tb_sound_player_set_state (TbSoundPlayer *player,
static void
tb_sound_player_set_filename (TbSoundPlayer *player,
- const char *filename)
+ const char *filename)
{
TbSoundPlayerPrivate *priv;
@@ -72,6 +83,132 @@ tb_sound_player_set_filename (TbSoundPlayer *player,
}
static void
+tb_sound_player_set_progress (TbSoundPlayer *player,
+ gdouble progress)
+{
+ TbSoundPlayerPrivate *priv;
+ GstState pending;
+ GstQuery *duration_q;
+ gint64 position;
+
+ priv = TB_SOUND_PLAYER_GET_PRIVATE (player);
+
+ if (!priv->pipeline)
+ return;
+
+ priv->target_progress = progress;
+
+ if (priv->in_seek)
+ {
+ priv->stacked_progress = progress;
+ return;
+ }
+
+ gst_element_get_state (priv->pipeline, &priv->stacked_state, &pending, 0);
+
+ if (pending)
+ priv->stacked_state = pending;
+
+ gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
+
+ duration_q = gst_query_new_duration (GST_FORMAT_TIME);
+
+ if (gst_element_query (priv->pipeline, duration_q))
+ {
+ gint64 duration = 0;
+
+ gst_query_parse_duration (duration_q, NULL, &duration);
+
+ position = progress * duration;
+ }
+ else
+ position = 0;
+
+ gst_query_unref (duration_q);
+
+ gst_element_seek (priv->pipeline,
+ 1.0,
+ GST_FORMAT_TIME,
+ GST_SEEK_FLAG_FLUSH,
+ GST_SEEK_TYPE_SET,
+ position,
+ GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
+
+ priv->in_seek = TRUE;
+ priv->stacked_progress = 0.0;
+}
+
+static gdouble
+tb_sound_player_get_progress (TbSoundPlayer *player)
+{
+ TbSoundPlayerPrivate *priv;
+ GstQuery *position_q, *duration_q;
+ gdouble progress;
+
+ priv = TB_SOUND_PLAYER_GET_PRIVATE (player);
+
+ if (!priv->pipeline)
+ return 0.0;
+
+ if (priv->in_seek)
+ {
+ return priv->target_progress;
+ }
+
+ position_q = gst_query_new_position (GST_FORMAT_TIME);
+ duration_q = gst_query_new_duration (GST_FORMAT_TIME);
+
+ if (gst_element_query (priv->pipeline, position_q) &&
+ gst_element_query (priv->pipeline, duration_q))
+ {
+ gint64 position, duration;
+
+ position = duration = 0;
+
+ gst_query_parse_position (position_q, NULL, &position);
+ gst_query_parse_duration (duration_q, NULL, &duration);
+
+ progress = CLAMP ((gdouble) position / (gdouble) duration, 0.0, 1.0);
+ }
+ else
+ progress = 0.0;
+
+ gst_query_unref (position_q);
+ gst_query_unref (duration_q);
+
+ return progress;
+}
+
+static void
+tb_sound_player_query_duration (TbSoundPlayer *player)
+{
+ TbSoundPlayerPrivate *priv;
+ GstFormat format = GST_FORMAT_TIME;
+ gdouble new_duration, difference;
+ gboolean success;
+ gint64 duration;
+
+ priv = TB_SOUND_PLAYER_GET_PRIVATE (player);
+
+ success = gst_element_query_duration (priv->pipeline, &format, &duration);
+
+ if (G_UNLIKELY (success != TRUE))
+ return;
+
+ new_duration = (gdouble) duration / GST_SECOND;
+
+ difference = ABS (priv->duration - new_duration);
+
+ if (difference > 1e-3)
+ {
+ priv->duration = new_duration;
+
+ if (difference > 1.0)
+ g_object_notify (G_OBJECT (player), "duration");
+ }
+}
+
+static void
tb_sound_player_reset_pipeline (TbSoundPlayer *player)
{
TbSoundPlayerPrivate *priv;
@@ -102,6 +239,11 @@ tb_sound_player_reset_pipeline (TbSoundPlayer *player)
gst_bus_async_signal_func (priv->bus, msg, NULL);
gst_element_set_state (priv->pipeline, GST_STATE_NULL);
+
+ priv->duration = 0;
+
+ g_object_notify (G_OBJECT (player), "duration");
+ g_object_notify (G_OBJECT (player), "progress");
}
static void
@@ -127,15 +269,24 @@ tb_sound_player_destroy_pipeline (TbSoundPlayer *player)
gst_object_unref (priv->pipeline);
priv->pipeline = NULL;
}
+
+ if (priv->tick_timeout_id != 0)
+ {
+ g_source_remove (priv->tick_timeout_id);
+ priv->tick_timeout_id = 0;
+ }
+
+ g_object_notify (G_OBJECT (player), "duration");
+ g_object_notify (G_OBJECT (player), "progress");
}
static void
-tb_sound_player_on_state_changed (GstBus *bus,
- GstMessage *msg,
+tb_sound_player_on_state_changed (GstBus *bus,
+ GstMessage *msg,
TbSoundPlayer *player)
{
TbSoundPlayerPrivate *priv;
- GstState state;
+ GstState state, old_state;
g_return_if_fail (TB_IS_SOUND_PLAYER (player));
@@ -144,7 +295,10 @@ tb_sound_player_on_state_changed (GstBus *bus,
if (msg->src != GST_OBJECT (priv->pipeline))
return;
- gst_message_parse_state_changed (msg, NULL, &state, NULL);
+ gst_message_parse_state_changed (msg, &old_state, &state, NULL);
+
+ if (state == GST_STATE_PAUSED && old_state == GST_STATE_READY)
+ tb_sound_player_query_duration (player);
switch (state)
{
@@ -164,8 +318,8 @@ tb_sound_player_on_state_changed (GstBus *bus,
}
static void
-tb_sound_player_on_error (GstBus *bus,
- GstMessage *msg,
+tb_sound_player_on_error (GstBus *bus,
+ GstMessage *msg,
TbSoundPlayer *player)
{
tb_sound_player_reset_pipeline (player);
@@ -173,14 +327,64 @@ tb_sound_player_on_error (GstBus *bus,
}
static void
-tb_sound_player_on_eos (GstBus *bus,
- GstMessage *msg,
+tb_sound_player_on_eos (GstBus *bus,
+ GstMessage *msg,
TbSoundPlayer *player)
{
+ g_object_notify (G_OBJECT (player), "progress");
+
tb_sound_player_set_state (player, TB_SOUND_PLAYER_STATE_DONE);
tb_sound_player_reset_pipeline (player);
}
+static void
+tb_sound_player_on_async_done (GstBus *bus,
+ GstMessage *msg,
+ TbSoundPlayer *player)
+{
+ TbSoundPlayerPrivate *priv;
+
+ priv = TB_SOUND_PLAYER_GET_PRIVATE (player);
+
+ if (priv->in_seek)
+ {
+ g_object_notify (G_OBJECT (player), "progress");
+
+ priv->in_seek = FALSE;
+ gst_element_set_state (priv->pipeline, priv->stacked_state);
+
+ if (priv->stacked_progress)
+ {
+ tb_sound_player_set_progress (player, priv->stacked_progress);
+ }
+ }
+}
+
+static void
+tb_sound_player_on_duration (GstBus *bus,
+ GstMessage *msg,
+ TbSoundPlayer *player)
+{
+ gint64 duration;
+
+ gst_message_parse_duration (msg, NULL, &duration);
+
+ if (G_UNLIKELY (duration != GST_CLOCK_TIME_NONE))
+ return;
+
+ tb_sound_player_query_duration (player);
+}
+
+static gboolean
+tb_sound_player_tick_timeout (gpointer user_data)
+{
+ GObject *player = user_data;
+
+ g_object_notify (player, "progress");
+
+ return TRUE;
+}
+
static gboolean
tb_sound_player_ensure_pipeline (TbSoundPlayer *player)
{
@@ -245,6 +449,24 @@ tb_sound_player_ensure_pipeline (TbSoundPlayer *player)
G_CALLBACK (tb_sound_player_on_eos),
player);
+ g_signal_connect (priv->bus,
+ "message::async-done",
+ G_CALLBACK (tb_sound_player_on_async_done),
+ player);
+
+ g_signal_connect (priv->bus,
+ "message::duration",
+ G_CALLBACK (tb_sound_player_on_duration),
+ player);
+
+ if (priv->tick_timeout_id == 0)
+ {
+ priv->tick_timeout_id =
+ g_timeout_add (TICK_TIMEOUT * 1000,
+ tb_sound_player_tick_timeout,
+ player);
+ }
+
return TRUE;
}
@@ -268,6 +490,7 @@ tb_sound_player_set_playing (TbSoundPlayer *player,
gst_element_set_state (priv->pipeline, state);
g_object_notify (G_OBJECT (player), "playing");
+ g_object_notify (G_OBJECT (player), "progress");
}
static gboolean
@@ -314,21 +537,32 @@ tb_sound_player_get_property (GObject *gobject,
GValue *value,
GParamSpec *pspec)
{
+ TbSoundPlayer *player;
TbSoundPlayerPrivate *priv;
- priv = TB_SOUND_PLAYER_GET_PRIVATE (gobject);
+ player = TB_SOUND_PLAYER (gobject);
+ priv = TB_SOUND_PLAYER_GET_PRIVATE (player);
switch (prop_id)
{
case PROP_PLAYING:
g_value_set_boolean (value,
- tb_sound_player_get_playing (TB_SOUND_PLAYER (gobject)));
+ tb_sound_player_get_playing (player));
break;
case PROP_STATE:
g_value_set_enum (value, priv->state);
break;
+ case PROP_PROGRESS:
+ g_value_set_double (value,
+ tb_sound_player_get_progress (player));
+ break;
+
+ case PROP_DURATION:
+ g_value_set_double (value, priv->duration);
+ break;
+
case PROP_FILENAME:
g_value_set_string (value, priv->filename);
break;
@@ -345,20 +579,27 @@ tb_sound_player_set_property (GObject *gobject,
const GValue *value,
GParamSpec *pspec)
{
+ TbSoundPlayer *player;
TbSoundPlayerPrivate *priv;
- priv = TB_SOUND_PLAYER_GET_PRIVATE (gobject);
+ player = TB_SOUND_PLAYER (gobject);
+ priv = TB_SOUND_PLAYER_GET_PRIVATE (player);
switch (prop_id)
{
case PROP_PLAYING:
- tb_sound_player_set_playing (TB_SOUND_PLAYER (gobject),
+ tb_sound_player_set_playing (player,
g_value_get_boolean (value));
break;
+ case PROP_PROGRESS:
+ tb_sound_player_set_progress (player,
+ g_value_get_double (value));
+ break;
+
case PROP_FILENAME:
- tb_sound_player_set_filename (TB_SOUND_PLAYER (gobject),
- g_value_get_string (value));
+ tb_sound_player_set_filename (player,
+ g_value_get_string (value));
break;
default:
@@ -390,6 +631,28 @@ tb_sound_player_class_init (TbSoundPlayerClass *klass)
g_object_class_install_property
(gobject_class,
+ PROP_PROGRESS,
+ g_param_spec_double ("progress",
+ "Progress",
+ "Player's playback progress",
+ 0.0,
+ 1.0,
+ 0.0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_DURATION,
+ g_param_spec_double ("duration",
+ "Duration",
+ "Sound duration",
+ 0.0,
+ G_MAXDOUBLE,
+ 0.0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property
+ (gobject_class,
PROP_STATE,
g_param_spec_enum ("state",
"State",
@@ -421,4 +684,7 @@ tb_sound_player_init (TbSoundPlayer *player)
player->priv->filename = NULL;
player->priv->pipeline = NULL;
player->priv->bus = NULL;
+ player->priv->stacked_progress = 0.0;
+ player->priv->duration = 0.0;
+ player->priv->tick_timeout_id = 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]