diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2016-07-19 14:36:25 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2016-07-25 13:02:35 +0300 |
commit | 6e39cef802f28257d36a400e445df36a52d2079e (patch) | |
tree | 955545100429ed33611896f96346668b3f5dbb6b | |
parent | 689468242631e950da8e535ffdb6eab61c2c25b9 (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.txt | 7 | ||||
-rw-r--r-- | gst-libs/gst/player/gstplayer.c | 166 | ||||
-rw-r--r-- | gst-libs/gst/player/gstplayer.h | 10 | ||||
-rw-r--r-- | tests/check/libs/player.c | 53 | ||||
-rw-r--r-- | win32/common/libgstplayer.def | 4 |
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 |