summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2016-07-19 14:36:25 +0200
committerSebastian Dröge <sebastian@centricular.com>2016-07-25 13:02:35 +0300
commit6e39cef802f28257d36a400e445df36a52d2079e (patch)
tree955545100429ed33611896f96346668b3f5dbb6b
parent689468242631e950da8e535ffdb6eab61c2c25b9 (diff)
player: add API to change http user agent
Introducing a new 'config' API similar to GstBufferPoolConfig. https://bugzilla.gnome.org/show_bug.cgi?id=765314
-rw-r--r--docs/libs/gst-plugins-bad-libs-sections.txt7
-rw-r--r--gst-libs/gst/player/gstplayer.c166
-rw-r--r--gst-libs/gst/player/gstplayer.h10
-rw-r--r--tests/check/libs/player.c53
-rw-r--r--win32/common/libgstplayer.def4
5 files changed, 240 insertions, 0 deletions
diff --git a/docs/libs/gst-plugins-bad-libs-sections.txt b/docs/libs/gst-plugins-bad-libs-sections.txt
index fdcdf2ed5..8e519361e 100644
--- a/docs/libs/gst-plugins-bad-libs-sections.txt
+++ b/docs/libs/gst-plugins-bad-libs-sections.txt
@@ -1705,6 +1705,9 @@ gst_player_get_mute
gst_player_get_pipeline
+gst_player_set_config
+gst_player_get_config
+
gst_player_set_position_update_interval
gst_player_get_position_update_interval
@@ -1763,6 +1766,10 @@ GstPlayerSignalDispatcherInterface
GstPlayerVideoRenderer
GstPlayerVideoRendererInterface
+<SUBSECTION config>
+gst_player_config_set_user_agent
+gst_player_config_get_user_agent
+
<SUBSECTION Standard>
GST_IS_PLAYER
GST_IS_PLAYER_CLASS
diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c
index 15d7d3459..01f00e33e 100644
--- a/gst-libs/gst/player/gstplayer.c
+++ b/gst-libs/gst/player/gstplayer.c
@@ -78,6 +78,24 @@ gst_player_error_quark (void)
return quark;
}
+static GQuark QUARK_CONFIG;
+
+/* Keep ConfigQuarkId and _config_quark_strings ordered and synced */
+typedef enum
+{
+ CONFIG_QUARK_USER_AGENT = 0,
+
+ CONFIG_QUARK_MAX
+} ConfigQuarkId;
+
+static const gchar *_config_quark_strings[] = {
+ "user-agent",
+};
+
+GQuark _config_quark_table[CONFIG_QUARK_MAX];
+
+#define CONFIG_QUARK(q) _config_quark_table[CONFIG_QUARK_##q]
+
enum
{
PROP_0,
@@ -161,6 +179,8 @@ struct _GstPlayer
GstElement *current_vis_element;
+ GstStructure *config;
+
/* Protected by lock */
gboolean seek_pending; /* Only set from main context */
GstClockTime last_seek_time; /* Only set from main context */
@@ -243,6 +263,8 @@ gst_player_init (GstPlayer * self)
self->context = g_main_context_new ();
self->loop = g_main_loop_new (self->context, FALSE);
+ self->config = gst_structure_new_id_empty (QUARK_CONFIG);
+
self->position_update_interval_ms = DEFAULT_POSITION_UPDATE_INTERVAL_MS;
self->seek_pending = FALSE;
self->seek_position = GST_CLOCK_TIME_NONE;
@@ -253,6 +275,23 @@ gst_player_init (GstPlayer * self)
}
static void
+config_quark_initialize (void)
+{
+ gint i;
+
+ QUARK_CONFIG = g_quark_from_static_string ("player-config");
+
+ if (G_N_ELEMENTS (_config_quark_strings) != CONFIG_QUARK_MAX)
+ g_warning ("the quark table is not consistent! %d != %d",
+ (int) G_N_ELEMENTS (_config_quark_strings), CONFIG_QUARK_MAX);
+
+ for (i = 0; i < CONFIG_QUARK_MAX; i++) {
+ _config_quark_table[i] =
+ g_quark_from_static_string (_config_quark_strings[i]);
+ }
+}
+
+static void
gst_player_class_init (GstPlayerClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
@@ -421,6 +460,8 @@ gst_player_class_init (GstPlayerClass * klass)
g_signal_new ("seek-done", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_CLOCK_TIME);
+
+ config_quark_initialize ();
}
static void
@@ -463,6 +504,8 @@ gst_player_finalize (GObject * object)
g_object_unref (self->signal_dispatcher);
if (self->current_vis_element)
gst_object_unref (self->current_vis_element);
+ if (self->config)
+ gst_structure_free (self->config);
g_mutex_clear (&self->lock);
g_cond_clear (&self->cond);
@@ -2488,6 +2531,26 @@ mute_notify_cb (G_GNUC_UNUSED GObject * obj, G_GNUC_UNUSED GParamSpec * pspec,
}
}
+static void
+source_setup_cb (GstElement * playbin, GstElement * source, GstPlayer * self)
+{
+ gchar *user_agent;
+
+ user_agent = gst_player_config_get_user_agent (self->config);
+ if (user_agent) {
+ GParamSpec *prop;
+
+ prop = g_object_class_find_property (G_OBJECT_GET_CLASS (source),
+ "user-agent");
+ if (prop && prop->value_type == G_TYPE_STRING) {
+ GST_INFO_OBJECT (self, "Setting source user-agent: %s", user_agent);
+ g_object_set (source, "user-agent", user_agent, NULL);
+ }
+
+ g_free (user_agent);
+ }
+}
+
static gpointer
gst_player_main (gpointer data)
{
@@ -2577,6 +2640,8 @@ gst_player_main (gpointer data)
G_CALLBACK (volume_notify_cb), self);
g_signal_connect (self->playbin, "notify::mute",
G_CALLBACK (mute_notify_cb), self);
+ g_signal_connect (self->playbin, "source-setup",
+ G_CALLBACK (source_setup_cb), self);
self->target_state = GST_STATE_NULL;
self->current_state = GST_STATE_NULL;
@@ -4061,3 +4126,104 @@ gst_player_error_get_name (GstPlayerError error)
g_assert_not_reached ();
return NULL;
}
+
+/**
+ * gst_player_set_config:
+ * @player: #GstPlayer instance
+ * @config: (transfer full): a #GstStructure
+ *
+ * Set the configuration of the player. If the player is already configured, and
+ * the configuration haven't change, this function will return %TRUE. If the
+ * player is not in the GST_PLAYER_STATE_STOPPED, this method will return %FALSE
+ * and active configuration will remain.
+ *
+ * @config is a #GstStructure that contains the configuration parameters for
+ * the player.
+ *
+ * This function takes ownership of @config.
+ *
+ * Returns: %TRUE when the configuration could be set.
+ * Since 1.10
+ */
+gboolean
+gst_player_set_config (GstPlayer * self, GstStructure * config)
+{
+ g_return_val_if_fail (GST_IS_PLAYER (self), FALSE);
+ g_return_val_if_fail (config != NULL, FALSE);
+
+ if (self->app_state != GST_PLAYER_STATE_STOPPED) {
+ GST_INFO_OBJECT (self, "can't change config while player is %s",
+ gst_player_state_get_name (self->app_state));
+ return FALSE;
+ }
+
+ if (self->config)
+ gst_structure_free (self->config);
+ self->config = config;
+
+ return TRUE;
+}
+
+/**
+ * gst_player_get_config:
+ * @player: #GstPlayer instance
+ *
+ * Get a copy of the current configuration of the player. This configuration
+ * can either be modified and used for the gst_player_set_config() call
+ * or it must be freed after usage.
+ *
+ * Returns: (transfer full): a copy of the current configuration of @player. Use
+ * gst_structure_free() after usage or gst_player_set_config().
+ * Since 1.10
+ */
+GstStructure *
+gst_player_get_config (GstPlayer * self)
+{
+ g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
+
+ return gst_structure_copy (self->config);
+}
+
+/**
+ * gst_player_config_set_user_agent:
+ * @config: a #GstPlayer configuration
+ * @agent: the string to use as user agent
+ *
+ * Set the user agent to pass to the server if @player needs to connect
+ * to a server during playback. This is typically used when playing HTTP
+ * or RTSP streams.
+ *
+ * Since 1.10
+ */
+void
+gst_player_config_set_user_agent (GstStructure * config, const gchar * agent)
+{
+ g_return_if_fail (config != NULL);
+ g_return_if_fail (agent != NULL);
+
+ gst_structure_id_set (config,
+ CONFIG_QUARK (USER_AGENT), G_TYPE_STRING, agent, NULL);
+}
+
+/**
+ * gst_player_config_get_user_agent:
+ * @config: a #GstPlayer configuration
+ *
+ * Return the user agent which has been configured using
+ * gst_player_config_set_user_agent() if any.
+ *
+ * Returns: (transfer full): the configured agent, or %NULL
+ * Since 1.10
+ */
+gchar *
+gst_player_config_get_user_agent (GstStructure * config)
+{
+ gchar *agent = NULL;
+
+ g_return_val_if_fail (config != NULL, NULL);
+
+ gst_structure_id_get (config,
+ CONFIG_QUARK (USER_AGENT), G_TYPE_STRING, &agent, NULL);
+
+ return agent;
+}
diff --git a/gst-libs/gst/player/gstplayer.h b/gst-libs/gst/player/gstplayer.h
index 0ab42333b..93b6d7294 100644
--- a/gst-libs/gst/player/gstplayer.h
+++ b/gst-libs/gst/player/gstplayer.h
@@ -192,6 +192,16 @@ gint64 gst_player_get_audio_video_offset (GstPlayer * player);
void gst_player_set_audio_video_offset (GstPlayer * player,
gint64 offset);
+gboolean gst_player_set_config (GstPlayer * player,
+ GstStructure * config);
+GstStructure * gst_player_get_config (GstPlayer * player);
+
+/* helpers for configuring the config structure */
+
+void gst_player_config_set_user_agent (GstStructure * config,
+ const gchar * agent);
+gchar * gst_player_config_get_user_agent (GstStructure * config);
+
G_END_DECLS
#endif /* __GST_PLAYER_H__ */
diff --git a/tests/check/libs/player.c b/tests/check/libs/player.c
index 52a7ca04a..e0fcf9266 100644
--- a/tests/check/libs/player.c
+++ b/tests/check/libs/player.c
@@ -1612,6 +1612,58 @@ START_TEST (test_restart)
END_TEST;
+#define TEST_USER_AGENT "test user agent"
+
+static void
+source_setup_cb (GstElement * playbin, GstElement * source, GMainLoop * loop)
+{
+ gchar *user_agent;
+
+ g_object_get (source, "user-agent", &user_agent, NULL);
+ fail_unless_equals_string (user_agent, TEST_USER_AGENT);
+ g_free (user_agent);
+
+ g_main_loop_quit (loop);
+}
+
+START_TEST (test_user_agent)
+{
+ GstPlayer *player;
+ GMainLoop *loop;
+ GstElement *pipeline;
+ GstStructure *config;
+ gchar *user_agent;
+
+ loop = g_main_loop_new (NULL, FALSE);
+ player = gst_player_new (NULL, NULL);
+ fail_unless (player != NULL);
+
+ gst_player_set_uri (player, "http://badger.com/test.mkv");
+
+ config = gst_player_get_config (player);
+ gst_player_config_set_user_agent (config, TEST_USER_AGENT);
+
+ user_agent = gst_player_config_get_user_agent (config);
+ fail_unless_equals_string (user_agent, TEST_USER_AGENT);
+ g_free (user_agent);
+
+ gst_player_set_config (player, config);
+
+ pipeline = gst_player_get_pipeline (player);
+ g_signal_connect (pipeline, "source-setup", G_CALLBACK (source_setup_cb),
+ loop);
+
+ gst_player_pause (player);
+ g_main_loop_run (loop);
+
+ gst_object_unref (pipeline);
+
+ g_object_unref (player);
+ g_main_loop_unref (loop);
+}
+
+END_TEST;
+
static Suite *
player_suite (void)
{
@@ -1654,6 +1706,7 @@ player_suite (void)
tcase_add_test (tc_general, test_play_backward_rate);
tcase_add_test (tc_general, test_play_audio_video_seek_done);
tcase_add_test (tc_general, test_restart);
+ tcase_add_test (tc_general, test_user_agent);
suite_add_tcase (s, tc_general);
diff --git a/win32/common/libgstplayer.def b/win32/common/libgstplayer.def
index 53fab85d3..09b74fb98 100644
--- a/win32/common/libgstplayer.def
+++ b/win32/common/libgstplayer.def
@@ -7,6 +7,8 @@ EXPORTS
gst_player_audio_info_get_type
gst_player_color_balance_type_get_name
gst_player_color_balance_type_get_type
+ gst_player_config_get_user_agent
+ gst_player_config_set_user_agent
gst_player_error_get_name
gst_player_error_get_type
gst_player_error_quark
@@ -15,6 +17,7 @@ EXPORTS
gst_player_get_audio_streams
gst_player_get_audio_video_offset
gst_player_get_color_balance
+ gst_player_get_config
gst_player_get_current_audio_track
gst_player_get_current_subtitle_track
gst_player_get_current_video_track
@@ -53,6 +56,7 @@ EXPORTS
gst_player_set_audio_track_enabled
gst_player_set_audio_video_offset
gst_player_set_color_balance
+ gst_player_set_config
gst_player_set_multiview_flags
gst_player_set_multiview_mode
gst_player_set_mute