| /* GStreamer Navigation |
| * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> |
| * Copyright (C) 2007-2009 Jan Schmidt <thaytan@noraisin.net> |
| * |
| * navigation.c: navigation event virtual class function wrappers |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| /** |
| * SECTION:gstnavigation |
| * @title: GstNavigation |
| * @short_description: Interface for creating, sending and parsing navigation |
| * events. |
| * |
| * The Navigation interface is used for creating and injecting navigation related |
| * events such as mouse button presses, cursor motion and key presses. The associated |
| * library also provides methods for parsing received events, and for sending and |
| * receiving navigation related bus events. One main usecase is DVD menu navigation. |
| * |
| * The main parts of the API are: |
| * |
| * * The GstNavigation interface, implemented by elements which provide an application |
| * with the ability to create and inject navigation events into the pipeline. |
| * * GstNavigation event handling API. GstNavigation events are created in response to |
| * calls on a GstNavigation interface implementation, and sent in the pipeline. Upstream |
| * elements can use the navigation event API functions to parse the contents of received |
| * messages. |
| * |
| * * GstNavigation message handling API. GstNavigation messages may be sent on the message |
| * bus to inform applications of navigation related changes in the pipeline, such as the |
| * mouse moving over a clickable region, or the set of available angles changing. |
| * |
| * The GstNavigation message functions provide functions for creating and parsing |
| * custom bus messages for signaling GstNavigation changes. |
| * |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| |
| #include <gst/video/navigation.h> |
| #include <gst/video/video-enumtypes.h> |
| |
| static void gst_navigation_class_init (GstNavigationInterface * iface); |
| |
| #define GST_NAVIGATION_MESSAGE_NAME "GstNavigationMessage" |
| #define GST_NAVIGATION_QUERY_NAME "GstNavigationQuery" |
| #define GST_NAVIGATION_EVENT_NAME "application/x-gst-navigation" |
| |
| #define WARN_IF_FAIL(exp,msg) if(G_UNLIKELY(!(exp))){g_warning("%s",(msg));} |
| |
| GType |
| gst_navigation_get_type (void) |
| { |
| static GType gst_navigation_type = 0; |
| |
| if (!gst_navigation_type) { |
| static const GTypeInfo gst_navigation_info = { |
| sizeof (GstNavigationInterface), |
| (GBaseInitFunc) gst_navigation_class_init, |
| NULL, |
| NULL, |
| NULL, |
| NULL, |
| 0, |
| 0, |
| NULL, |
| }; |
| |
| gst_navigation_type = g_type_register_static (G_TYPE_INTERFACE, |
| "GstNavigation", &gst_navigation_info, 0); |
| } |
| |
| return gst_navigation_type; |
| } |
| |
| static void |
| gst_navigation_class_init (GstNavigationInterface * iface) |
| { |
| /* default virtual functions */ |
| iface->send_event = NULL; |
| } |
| |
| /* The interface implementer should make sure that the object can handle |
| * the event. */ |
| void |
| gst_navigation_send_event (GstNavigation * navigation, GstStructure * structure) |
| { |
| GstNavigationInterface *iface = GST_NAVIGATION_GET_INTERFACE (navigation); |
| |
| if (iface->send_event) { |
| iface->send_event (navigation, structure); |
| } else { |
| gst_structure_free (structure); |
| } |
| } |
| |
| /** |
| * gst_navigation_send_key_event: |
| * @navigation: The navigation interface instance |
| * @event: The type of the key event. Recognised values are "key-press" and |
| * "key-release" |
| * @key: Character representation of the key. This is typically as produced |
| * by XKeysymToString. |
| */ |
| void |
| gst_navigation_send_key_event (GstNavigation * navigation, const char *event, |
| const char *key) |
| { |
| g_return_if_fail (g_strcmp0 (event, "key-press") == 0 || |
| g_strcmp0 (event, "key-release") == 0); |
| |
| gst_navigation_send_event (navigation, |
| gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, |
| event, "key", G_TYPE_STRING, key, NULL)); |
| } |
| |
| /** |
| * gst_navigation_send_mouse_event: |
| * @navigation: The navigation interface instance |
| * @event: The type of mouse event, as a text string. Recognised values are |
| * "mouse-button-press", "mouse-button-release" and "mouse-move". |
| * @button: The button number of the button being pressed or released. Pass 0 |
| * for mouse-move events. |
| * @x: The x coordinate of the mouse event. |
| * @y: The y coordinate of the mouse event. |
| * |
| * Sends a mouse event to the navigation interface. Mouse event coordinates |
| * are sent relative to the display space of the related output area. This is |
| * usually the size in pixels of the window associated with the element |
| * implementing the #GstNavigation interface. |
| * |
| */ |
| void |
| gst_navigation_send_mouse_event (GstNavigation * navigation, const char *event, |
| int button, double x, double y) |
| { |
| g_return_if_fail (g_strcmp0 (event, "mouse-button-press") == 0 || |
| g_strcmp0 (event, "mouse-button-release") == 0 || |
| g_strcmp0 (event, "mouse-move") == 0); |
| |
| gst_navigation_send_event (navigation, |
| gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, |
| event, "button", G_TYPE_INT, button, "pointer_x", G_TYPE_DOUBLE, x, |
| "pointer_y", G_TYPE_DOUBLE, y, NULL)); |
| } |
| |
| /** |
| * gst_navigation_send_command: |
| * @navigation: The navigation interface instance |
| * @command: The command to issue |
| * |
| * Sends the indicated command to the navigation interface. |
| */ |
| void |
| gst_navigation_send_command (GstNavigation * navigation, |
| GstNavigationCommand command) |
| { |
| gst_navigation_send_event (navigation, |
| gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, |
| "command", "command-code", G_TYPE_UINT, (guint) command, NULL)); |
| } |
| |
| /* Navigation Queries */ |
| |
| #define GST_NAVIGATION_QUERY_HAS_TYPE(query,query_type) \ |
| (gst_navigation_query_get_type (query) == GST_NAVIGATION_QUERY_ ## query_type) |
| |
| /** |
| * gst_navigation_query_get_type: |
| * @query: The query to inspect |
| * |
| * Inspect a #GstQuery and return the #GstNavigationQueryType associated with |
| * it if it is a #GstNavigation query. |
| * |
| * Returns: The #GstNavigationQueryType of the query, or |
| * #GST_NAVIGATION_QUERY_INVALID |
| */ |
| GstNavigationQueryType |
| gst_navigation_query_get_type (GstQuery * query) |
| { |
| const GstStructure *s; |
| const gchar *q_type; |
| |
| if (query == NULL || GST_QUERY_TYPE (query) != GST_QUERY_CUSTOM) |
| return GST_NAVIGATION_QUERY_INVALID; |
| |
| s = gst_query_get_structure (query); |
| if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_QUERY_NAME)) |
| return GST_NAVIGATION_QUERY_INVALID; |
| |
| q_type = gst_structure_get_string (s, "type"); |
| if (q_type == NULL) |
| return GST_NAVIGATION_QUERY_INVALID; |
| |
| if (g_str_equal (q_type, "commands")) |
| return GST_NAVIGATION_QUERY_COMMANDS; |
| else if (g_str_equal (q_type, "angles")) |
| return GST_NAVIGATION_QUERY_ANGLES; |
| |
| return GST_NAVIGATION_QUERY_INVALID; |
| } |
| |
| /** |
| * gst_navigation_query_new_commands: |
| * |
| * Create a new #GstNavigation commands query. When executed, it will |
| * query the pipeline for the set of currently available commands. |
| * |
| * Returns: The new query. |
| */ |
| GstQuery * |
| gst_navigation_query_new_commands (void) |
| { |
| GstQuery *query; |
| GstStructure *structure; |
| |
| structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME, |
| "type", G_TYPE_STRING, "commands", NULL); |
| query = gst_query_new_custom (GST_QUERY_CUSTOM, structure); |
| |
| return query; |
| } |
| |
| static void |
| gst_query_list_add_command (GValue * list, GstNavigationCommand val) |
| { |
| GValue item = { 0, }; |
| |
| g_value_init (&item, GST_TYPE_NAVIGATION_COMMAND); |
| g_value_set_enum (&item, val); |
| gst_value_list_append_value (list, &item); |
| g_value_unset (&item); |
| } |
| |
| /** |
| * gst_navigation_query_set_commands: |
| * @query: a #GstQuery |
| * @n_cmds: the number of commands to set. |
| * @...: A list of @GstNavigationCommand values, @n_cmds entries long. |
| * |
| * Set the #GstNavigation command query result fields in @query. The number |
| * of commands passed must be equal to @n_commands. |
| */ |
| void |
| gst_navigation_query_set_commands (GstQuery * query, gint n_cmds, ...) |
| { |
| va_list ap; |
| GValue list = { 0, }; |
| GstStructure *structure; |
| gint i; |
| |
| g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS)); |
| |
| g_value_init (&list, GST_TYPE_LIST); |
| |
| va_start (ap, n_cmds); |
| for (i = 0; i < n_cmds; i++) { |
| GstNavigationCommand val = va_arg (ap, GstNavigationCommand); |
| gst_query_list_add_command (&list, val); |
| } |
| va_end (ap); |
| |
| structure = gst_query_writable_structure (query); |
| gst_structure_take_value (structure, "commands", &list); |
| } |
| |
| /** |
| * gst_navigation_query_set_commandsv: |
| * @query: a #GstQuery |
| * @n_cmds: the number of commands to set. |
| * @cmds: (array length=n_cmds): An array containing @n_cmds |
| * @GstNavigationCommand values. |
| * |
| * Set the #GstNavigation command query result fields in @query. The number |
| * of commands passed must be equal to @n_commands. |
| */ |
| void |
| gst_navigation_query_set_commandsv (GstQuery * query, gint n_cmds, |
| GstNavigationCommand * cmds) |
| { |
| GValue list = { 0, }; |
| GstStructure *structure; |
| gint i; |
| |
| g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS)); |
| |
| g_value_init (&list, GST_TYPE_LIST); |
| for (i = 0; i < n_cmds; i++) { |
| gst_query_list_add_command (&list, cmds[i]); |
| } |
| structure = gst_query_writable_structure (query); |
| gst_structure_take_value (structure, "commands", &list); |
| } |
| |
| /** |
| * gst_navigation_query_parse_commands_length: |
| * @query: a #GstQuery |
| * @n_cmds: (out) (optional): the number of commands in this query. |
| * |
| * Parse the number of commands in the #GstNavigation commands @query. |
| * |
| * Returns: %TRUE if the query could be successfully parsed. %FALSE if not. |
| */ |
| gboolean |
| gst_navigation_query_parse_commands_length (GstQuery * query, guint * n_cmds) |
| { |
| const GstStructure *structure; |
| const GValue *list; |
| |
| g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE); |
| |
| if (n_cmds == NULL) |
| return TRUE; |
| |
| structure = gst_query_get_structure (query); |
| list = gst_structure_get_value (structure, "commands"); |
| if (list == NULL) |
| *n_cmds = 0; |
| else |
| *n_cmds = gst_value_list_get_size (list); |
| |
| return TRUE; |
| } |
| |
| /** |
| * gst_navigation_query_parse_commands_nth: |
| * @query: a #GstQuery |
| * @nth: the nth command to retrieve. |
| * @cmd: (out) (optional): a pointer to store the nth command into. |
| * |
| * Parse the #GstNavigation command query and retrieve the @nth command from |
| * it into @cmd. If the list contains less elements than @nth, @cmd will be |
| * set to #GST_NAVIGATION_COMMAND_INVALID. |
| * |
| * Returns: %TRUE if the query could be successfully parsed. %FALSE if not. |
| */ |
| gboolean |
| gst_navigation_query_parse_commands_nth (GstQuery * query, guint nth, |
| GstNavigationCommand * cmd) |
| { |
| const GstStructure *structure; |
| const GValue *list; |
| |
| g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE); |
| |
| if (cmd == NULL) |
| return TRUE; |
| |
| structure = gst_query_get_structure (query); |
| list = gst_structure_get_value (structure, "commands"); |
| if (list == NULL) { |
| *cmd = GST_NAVIGATION_COMMAND_INVALID; |
| } else { |
| if (nth < gst_value_list_get_size (list)) { |
| *cmd = (GstNavigationCommand) |
| g_value_get_enum (gst_value_list_get_value (list, nth)); |
| } else |
| *cmd = GST_NAVIGATION_COMMAND_INVALID; |
| } |
| |
| return TRUE; |
| } |
| |
| /** |
| * gst_navigation_query_new_angles: |
| * |
| * Create a new #GstNavigation angles query. When executed, it will |
| * query the pipeline for the set of currently available angles, which may be |
| * greater than one in a multiangle video. |
| * |
| * Returns: The new query. |
| */ |
| GstQuery * |
| gst_navigation_query_new_angles (void) |
| { |
| GstQuery *query; |
| GstStructure *structure; |
| |
| structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME, |
| "type", G_TYPE_STRING, "angles", NULL); |
| query = gst_query_new_custom (GST_QUERY_CUSTOM, structure); |
| |
| return query; |
| } |
| |
| /** |
| * gst_navigation_query_set_angles: |
| * @query: a #GstQuery |
| * @cur_angle: the current viewing angle to set. |
| * @n_angles: the number of viewing angles to set. |
| * |
| * Set the #GstNavigation angles query result field in @query. |
| */ |
| void |
| gst_navigation_query_set_angles (GstQuery * query, guint cur_angle, |
| guint n_angles) |
| { |
| GstStructure *structure; |
| |
| g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES)); |
| |
| structure = gst_query_writable_structure (query); |
| gst_structure_set (structure, |
| "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL); |
| } |
| |
| /** |
| * gst_navigation_query_parse_angles: |
| * @query: a #GstQuery |
| * @cur_angle: (out) (optional): Pointer to a #guint into which to store the |
| * currently selected angle value from the query, or NULL |
| * @n_angles: (out) (optional): Pointer to a #guint into which to store the |
| * number of angles value from the query, or NULL |
| * |
| * Parse the current angle number in the #GstNavigation angles @query into the |
| * #guint pointed to by the @cur_angle variable, and the number of available |
| * angles into the #guint pointed to by the @n_angles variable. |
| * |
| * Returns: %TRUE if the query could be successfully parsed. %FALSE if not. |
| */ |
| gboolean |
| gst_navigation_query_parse_angles (GstQuery * query, guint * cur_angle, |
| guint * n_angles) |
| { |
| const GstStructure *structure; |
| gboolean ret = TRUE; |
| |
| g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES), FALSE); |
| |
| structure = gst_query_get_structure (query); |
| |
| if (cur_angle) |
| ret &= gst_structure_get_uint (structure, "angle", cur_angle); |
| |
| if (n_angles) |
| ret &= gst_structure_get_uint (structure, "angles", n_angles); |
| |
| WARN_IF_FAIL (ret, "Couldn't extract details from angles query"); |
| |
| return ret; |
| } |
| |
| /* Navigation Messages */ |
| |
| #define GST_NAVIGATION_MESSAGE_HAS_TYPE(msg,msg_type) \ |
| (gst_navigation_message_get_type (msg) == GST_NAVIGATION_MESSAGE_ ## msg_type) |
| |
| /** |
| * gst_navigation_message_get_type: |
| * @message: A #GstMessage to inspect. |
| * |
| * Check a bus message to see if it is a #GstNavigation event, and return |
| * the #GstNavigationMessageType identifying the type of the message if so. |
| * |
| * Returns: The type of the #GstMessage, or |
| * #GST_NAVIGATION_MESSAGE_INVALID if the message is not a #GstNavigation |
| * notification. |
| */ |
| GstNavigationMessageType |
| gst_navigation_message_get_type (GstMessage * message) |
| { |
| const GstStructure *s; |
| const gchar *m_type; |
| |
| if (message == NULL || GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) |
| return GST_NAVIGATION_MESSAGE_INVALID; |
| |
| s = gst_message_get_structure (message); |
| if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_MESSAGE_NAME)) |
| return GST_NAVIGATION_MESSAGE_INVALID; |
| |
| m_type = gst_structure_get_string (s, "type"); |
| if (m_type == NULL) |
| return GST_NAVIGATION_MESSAGE_INVALID; |
| |
| if (g_str_equal (m_type, "mouse-over")) |
| return GST_NAVIGATION_MESSAGE_MOUSE_OVER; |
| else if (g_str_equal (m_type, "commands-changed")) |
| return GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED; |
| else if (g_str_equal (m_type, "angles-changed")) |
| return GST_NAVIGATION_MESSAGE_ANGLES_CHANGED; |
| else if (g_str_equal (m_type, "event")) |
| return GST_NAVIGATION_MESSAGE_EVENT; |
| |
| return GST_NAVIGATION_MESSAGE_INVALID; |
| } |
| |
| /** |
| * gst_navigation_message_new_mouse_over: |
| * @src: A #GstObject to set as source of the new message. |
| * @active: %TRUE if the mouse has entered a clickable area of the display. |
| * %FALSE if it over a non-clickable area. |
| * |
| * Creates a new #GstNavigation message with type |
| * #GST_NAVIGATION_MESSAGE_MOUSE_OVER. |
| * |
| * Returns: The new #GstMessage. |
| */ |
| GstMessage * |
| gst_navigation_message_new_mouse_over (GstObject * src, gboolean active) |
| { |
| GstStructure *s; |
| GstMessage *m; |
| |
| s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME, |
| "type", G_TYPE_STRING, "mouse-over", "active", G_TYPE_BOOLEAN, active, |
| NULL); |
| |
| m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s); |
| |
| return m; |
| } |
| |
| /** |
| * gst_navigation_message_parse_mouse_over: |
| * @message: A #GstMessage to inspect. |
| * @active: (out) (optional): A pointer to a gboolean to receive the |
| * active/inactive state, or NULL. |
| * |
| * Parse a #GstNavigation message of type #GST_NAVIGATION_MESSAGE_MOUSE_OVER |
| * and extract the active/inactive flag. If the mouse over event is marked |
| * active, it indicates that the mouse is over a clickable area. |
| * |
| * Returns: %TRUE if the message could be successfully parsed. %FALSE if not. |
| */ |
| gboolean |
| gst_navigation_message_parse_mouse_over (GstMessage * message, |
| gboolean * active) |
| { |
| if (!GST_NAVIGATION_MESSAGE_HAS_TYPE (message, MOUSE_OVER)) |
| return FALSE; |
| |
| if (active) { |
| const GstStructure *s = gst_message_get_structure (message); |
| if (!gst_structure_get_boolean (s, "active", active)) |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| /** |
| * gst_navigation_message_new_event: |
| * @src: A #GstObject to set as source of the new message. |
| * @event: (transfer none): A navigation #GstEvent |
| * |
| * Creates a new #GstNavigation message with type |
| * #GST_NAVIGATION_MESSAGE_EVENT. |
| * |
| * Returns: The new #GstMessage. |
| * |
| * Since: 1.6 |
| */ |
| GstMessage * |
| gst_navigation_message_new_event (GstObject * src, GstEvent * event) |
| { |
| GstStructure *s; |
| GstMessage *m; |
| |
| s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME, |
| "type", G_TYPE_STRING, "event", "event", GST_TYPE_EVENT, event, NULL); |
| |
| m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s); |
| |
| return m; |
| } |
| |
| /** |
| * gst_navigation_message_parse_event: |
| * @message: A #GstMessage to inspect. |
| * @event: (out) (optional) (transfer full): a pointer to a #GstEvent to receive |
| * the contained navigation event. |
| * |
| * Parse a #GstNavigation message of type #GST_NAVIGATION_MESSAGE_EVENT |
| * and extract contained #GstEvent. The caller must unref the @event when done |
| * with it. |
| * |
| * Returns: %TRUE if the message could be successfully parsed. %FALSE if not. |
| * |
| * Since: 1.6 |
| */ |
| gboolean |
| gst_navigation_message_parse_event (GstMessage * message, GstEvent ** event) |
| { |
| if (!GST_NAVIGATION_MESSAGE_HAS_TYPE (message, EVENT)) |
| return FALSE; |
| |
| if (event) { |
| const GstStructure *s = gst_message_get_structure (message); |
| if (!gst_structure_get (s, "event", GST_TYPE_EVENT, event, NULL)) |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| /** |
| * gst_navigation_message_new_commands_changed: |
| * @src: A #GstObject to set as source of the new message. |
| * |
| * Creates a new #GstNavigation message with type |
| * #GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED |
| * |
| * Returns: The new #GstMessage. |
| */ |
| GstMessage * |
| gst_navigation_message_new_commands_changed (GstObject * src) |
| { |
| GstStructure *s; |
| GstMessage *m; |
| |
| s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME, |
| "type", G_TYPE_STRING, "commands-changed", NULL); |
| |
| m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s); |
| |
| return m; |
| } |
| |
| /** |
| * gst_navigation_message_new_angles_changed: |
| * @src: A #GstObject to set as source of the new message. |
| * @cur_angle: The currently selected angle. |
| * @n_angles: The number of viewing angles now available. |
| * |
| * Creates a new #GstNavigation message with type |
| * #GST_NAVIGATION_MESSAGE_ANGLES_CHANGED for notifying an application |
| * that the current angle, or current number of angles available in a |
| * multiangle video has changed. |
| * |
| * Returns: The new #GstMessage. |
| */ |
| GstMessage * |
| gst_navigation_message_new_angles_changed (GstObject * src, guint cur_angle, |
| guint n_angles) |
| { |
| GstStructure *s; |
| GstMessage *m; |
| |
| s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME, |
| "type", G_TYPE_STRING, "angles-changed", |
| "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL); |
| |
| m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s); |
| |
| return m; |
| } |
| |
| /** |
| * gst_navigation_message_parse_angles_changed: |
| * @message: A #GstMessage to inspect. |
| * @cur_angle: (out) (optional): A pointer to a #guint to receive the new |
| * current angle number, or NULL |
| * @n_angles: (out) (optional): A pointer to a #guint to receive the new angle |
| * count, or NULL. |
| * |
| * Parse a #GstNavigation message of type GST_NAVIGATION_MESSAGE_ANGLES_CHANGED |
| * and extract the @cur_angle and @n_angles parameters. |
| * |
| * Returns: %TRUE if the message could be successfully parsed. %FALSE if not. |
| */ |
| gboolean |
| gst_navigation_message_parse_angles_changed (GstMessage * message, |
| guint * cur_angle, guint * n_angles) |
| { |
| const GstStructure *s; |
| gboolean ret = TRUE; |
| |
| g_return_val_if_fail (GST_NAVIGATION_MESSAGE_HAS_TYPE (message, |
| ANGLES_CHANGED), FALSE); |
| |
| s = gst_message_get_structure (message); |
| if (cur_angle) |
| ret &= gst_structure_get_uint (s, "angle", cur_angle); |
| |
| if (n_angles) |
| ret &= gst_structure_get_uint (s, "angles", n_angles); |
| |
| WARN_IF_FAIL (ret, "Couldn't extract details from angles-changed event"); |
| |
| return ret; |
| } |
| |
| #define GST_NAVIGATION_EVENT_HAS_TYPE(event,event_type) \ |
| (gst_navigation_event_get_type (event) == GST_NAVIGATION_EVENT_ ## event_type) |
| |
| /** |
| * gst_navigation_event_get_type: |
| * @event: A #GstEvent to inspect. |
| * |
| * Inspect a #GstEvent and return the #GstNavigationEventType of the event, or |
| * #GST_NAVIGATION_EVENT_INVALID if the event is not a #GstNavigation event. |
| */ |
| GstNavigationEventType |
| gst_navigation_event_get_type (GstEvent * event) |
| { |
| const GstStructure *s; |
| const gchar *e_type; |
| |
| if (event == NULL || GST_EVENT_TYPE (event) != GST_EVENT_NAVIGATION) |
| return GST_NAVIGATION_EVENT_INVALID; |
| |
| s = gst_event_get_structure (event); |
| if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_EVENT_NAME)) |
| return GST_NAVIGATION_EVENT_INVALID; |
| |
| e_type = gst_structure_get_string (s, "event"); |
| if (e_type == NULL) |
| return GST_NAVIGATION_EVENT_INVALID; |
| |
| if (g_str_equal (e_type, "mouse-button-press")) |
| return GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS; |
| else if (g_str_equal (e_type, "mouse-button-release")) |
| return GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE; |
| else if (g_str_equal (e_type, "mouse-move")) |
| return GST_NAVIGATION_EVENT_MOUSE_MOVE; |
| else if (g_str_equal (e_type, "key-press")) |
| return GST_NAVIGATION_EVENT_KEY_PRESS; |
| else if (g_str_equal (e_type, "key-release")) |
| return GST_NAVIGATION_EVENT_KEY_RELEASE; |
| else if (g_str_equal (e_type, "command")) |
| return GST_NAVIGATION_EVENT_COMMAND; |
| |
| return GST_NAVIGATION_EVENT_INVALID; |
| } |
| |
| /** |
| * gst_navigation_event_parse_key_event: |
| * @event: A #GstEvent to inspect. |
| * @key: (out) (optional) (transfer none): A pointer to a location to receive |
| * the string identifying the key press. The returned string is owned by the |
| * event, and valid only until the event is unreffed. |
| */ |
| gboolean |
| gst_navigation_event_parse_key_event (GstEvent * event, const gchar ** key) |
| { |
| GstNavigationEventType e_type; |
| const GstStructure *s; |
| |
| e_type = gst_navigation_event_get_type (event); |
| g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_KEY_PRESS || |
| e_type == GST_NAVIGATION_EVENT_KEY_RELEASE, FALSE); |
| |
| if (key) { |
| s = gst_event_get_structure (event); |
| *key = gst_structure_get_string (s, "key"); |
| if (*key == NULL) |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| /** |
| * gst_navigation_event_parse_mouse_button_event: |
| * @event: A #GstEvent to inspect. |
| * @button: (out) (optional): Pointer to a gint that will receive the button |
| * number associated with the event. |
| * @x: (out) (optional): Pointer to a gdouble to receive the x coordinate of the |
| * mouse button event. |
| * @y: (out) (optional): Pointer to a gdouble to receive the y coordinate of the |
| * mouse button event. |
| * |
| * Retrieve the details of either a #GstNavigation mouse button press event or |
| * a mouse button release event. Determine which type the event is using |
| * gst_navigation_event_get_type() to retrieve the #GstNavigationEventType. |
| * |
| * Returns: TRUE if the button number and both coordinates could be extracted, |
| * otherwise FALSE. |
| */ |
| gboolean |
| gst_navigation_event_parse_mouse_button_event (GstEvent * event, gint * button, |
| gdouble * x, gdouble * y) |
| { |
| GstNavigationEventType e_type; |
| const GstStructure *s; |
| gboolean ret = TRUE; |
| |
| e_type = gst_navigation_event_get_type (event); |
| g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS || |
| e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE, FALSE); |
| |
| s = gst_event_get_structure (event); |
| if (x) |
| ret &= gst_structure_get_double (s, "pointer_x", x); |
| if (y) |
| ret &= gst_structure_get_double (s, "pointer_y", y); |
| if (button) |
| ret &= gst_structure_get_int (s, "button", button); |
| |
| WARN_IF_FAIL (ret, "Couldn't extract details from mouse button event"); |
| |
| return ret; |
| } |
| |
| /** |
| * gst_navigation_event_parse_mouse_move_event: |
| * @event: A #GstEvent to inspect. |
| * @x: (out) (optional): Pointer to a gdouble to receive the x coordinate of the |
| * mouse movement. |
| * @y: (out) (optional): Pointer to a gdouble to receive the y coordinate of the |
| * mouse movement. |
| * |
| * Inspect a #GstNavigation mouse movement event and extract the coordinates |
| * of the event. |
| * |
| * Returns: TRUE if both coordinates could be extracted, otherwise FALSE. |
| */ |
| gboolean |
| gst_navigation_event_parse_mouse_move_event (GstEvent * event, gdouble * x, |
| gdouble * y) |
| { |
| const GstStructure *s; |
| gboolean ret = TRUE; |
| |
| g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, MOUSE_MOVE), |
| FALSE); |
| |
| s = gst_event_get_structure (event); |
| if (x) |
| ret &= gst_structure_get_double (s, "pointer_x", x); |
| if (y) |
| ret &= gst_structure_get_double (s, "pointer_y", y); |
| |
| WARN_IF_FAIL (ret, "Couldn't extract positions from mouse move event"); |
| |
| return ret; |
| } |
| |
| /** |
| * gst_navigation_event_parse_command: |
| * @event: A #GstEvent to inspect. |
| * @command: (out) (optional): Pointer to GstNavigationCommand to receive the |
| * type of the navigation event. |
| * |
| * Inspect a #GstNavigation command event and retrieve the enum value of the |
| * associated command. |
| * |
| * Returns: TRUE if the navigation command could be extracted, otherwise FALSE. |
| */ |
| gboolean |
| gst_navigation_event_parse_command (GstEvent * event, |
| GstNavigationCommand * command) |
| { |
| const GstStructure *s; |
| gboolean ret = TRUE; |
| |
| g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, COMMAND), FALSE); |
| |
| if (command) { |
| s = gst_event_get_structure (event); |
| ret = gst_structure_get_uint (s, "command-code", (guint *) command); |
| WARN_IF_FAIL (ret, "Couldn't extract command code from command event"); |
| } |
| |
| return ret; |
| } |