1 /* GStreamer Navigation
2 * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 * Copyright (C) 2007-2009 Jan Schmidt <thaytan@noraisin.net>
5 * navigation.c: navigation event virtual class function wrappers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 * SECTION:gstnavigation
25 * @short_description: Interface for creating, sending and parsing navigation
28 * The Navigation interface is used for creating and injecting navigation related
29 * events such as mouse button presses, cursor motion and key presses. The associated
30 * library also provides methods for parsing received events, and for sending and
31 * receiving navigation related bus events. One main usecase is DVD menu navigation.
33 * The main parts of the API are:
37 * The GstNavigation interface, implemented by elements which provide an application
38 * with the ability to create and inject navigation events into the pipeline.
43 * GstNavigation event handling API. GstNavigation events are created in response to
44 * calls on a GstNavigation interface implementation, and sent in the pipeline. Upstream
45 * elements can use the navigation event API functions to parse the contents of received
51 * GstNavigation message handling API. GstNavigation messages may be sent on the message
52 * bus to inform applications of navigation related changes in the pipeline, such as the
53 * mouse moving over a clickable region, or the set of available angles changing.
55 * The GstNavigation message functions provide functions for creating and parsing
56 * custom bus messages for signaling GstNavigation changes.
66 #include <gst/interfaces/navigation.h>
67 #include <gst/interfaces/interfaces-enumtypes.h>
69 static void gst_navigation_class_init (GstNavigationInterface * iface);
71 #define GST_NAVIGATION_MESSAGE_NAME "GstNavigationMessage"
72 #define GST_NAVIGATION_QUERY_NAME "GstNavigationQuery"
73 #define GST_NAVIGATION_EVENT_NAME "application/x-gst-navigation"
75 #define WARN_IF_FAIL(exp,msg) if(G_UNLIKELY(!(exp))){g_warning("%s",(msg));}
78 gst_navigation_get_type (void)
80 static GType gst_navigation_type = 0;
82 if (!gst_navigation_type) {
83 static const GTypeInfo gst_navigation_info = {
84 sizeof (GstNavigationInterface),
85 (GBaseInitFunc) gst_navigation_class_init,
95 gst_navigation_type = g_type_register_static (G_TYPE_INTERFACE,
96 "GstNavigation", &gst_navigation_info, 0);
99 return gst_navigation_type;
103 gst_navigation_class_init (GstNavigationInterface * iface)
105 /* default virtual functions */
106 iface->send_event = NULL;
109 /* The interface implementer should make sure that the object can handle
112 gst_navigation_send_event (GstNavigation * navigation, GstStructure * structure)
114 GstNavigationInterface *iface = GST_NAVIGATION_GET_IFACE (navigation);
116 if (iface->send_event) {
117 iface->send_event (navigation, structure);
122 * gst_navigation_send_key_event:
123 * @navigation: The navigation interface instance
124 * @event: The type of the key event. Recognised values are "key-press" and
126 * @key: Character representation of the key. This is typically as produced
127 * by XKeysymToString.
130 gst_navigation_send_key_event (GstNavigation * navigation, const char *event,
133 gst_navigation_send_event (navigation,
134 gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING,
135 event, "key", G_TYPE_STRING, key, NULL));
139 * gst_navigation_send_mouse_event:
140 * @navigation: The navigation interface instance
141 * @event: The type of mouse event, as a text string. Recognised values are
142 * "mouse-button-press", "mouse-button-release" and "mouse-move".
143 * @button: The button number of the button being pressed or released. Pass 0
144 * for mouse-move events.
145 * @x: The x coordinate of the mouse event.
146 * @y: The y coordinate of the mouse event.
148 * Sends a mouse event to the navigation interface. Mouse event coordinates
149 * are sent relative to the display space of the related output area. This is
150 * usually the size in pixels of the window associated with the element
151 * implementing the #GstNavigation interface.
155 gst_navigation_send_mouse_event (GstNavigation * navigation, const char *event,
156 int button, double x, double y)
158 gst_navigation_send_event (navigation,
159 gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING,
160 event, "button", G_TYPE_INT, button, "pointer_x", G_TYPE_DOUBLE, x,
161 "pointer_y", G_TYPE_DOUBLE, y, NULL));
165 * gst_navigation_send_command:
166 * @navigation: The navigation interface instance
167 * @command: The command to issue
169 * Sends the indicated command to the navigation interface.
174 gst_navigation_send_command (GstNavigation * navigation,
175 GstNavigationCommand command)
177 gst_navigation_send_event (navigation,
178 gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING,
179 "command", "command-code", G_TYPE_UINT, (guint) command, NULL));
182 /* Navigation Queries */
184 #define GST_NAVIGATION_QUERY_HAS_TYPE(query,query_type) \
185 (gst_navigation_query_get_type (query) == GST_NAVIGATION_QUERY_ ## query_type)
188 * gst_navigation_query_get_type:
189 * @query: The query to inspect
191 * Inspect a #GstQuery and return the #GstNavigationQueryType associated with
192 * it if it is a #GstNavigation query.
194 * Returns: The #GstNavigationQueryType of the query, or
195 * #GST_NAVIGATION_QUERY_INVALID
198 GstNavigationQueryType
199 gst_navigation_query_get_type (GstQuery * query)
201 const GstStructure *s;
204 if (query == NULL || GST_QUERY_TYPE (query) != GST_QUERY_CUSTOM)
205 return GST_NAVIGATION_QUERY_INVALID;
207 s = gst_query_get_structure (query);
208 if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_QUERY_NAME))
209 return GST_NAVIGATION_QUERY_INVALID;
211 q_type = gst_structure_get_string (s, "type");
213 return GST_NAVIGATION_QUERY_INVALID;
215 if (g_str_equal (q_type, "commands"))
216 return GST_NAVIGATION_QUERY_COMMANDS;
217 else if (g_str_equal (q_type, "angles"))
218 return GST_NAVIGATION_QUERY_ANGLES;
220 return GST_NAVIGATION_QUERY_INVALID;
224 * gst_navigation_query_new_commands:
226 * Create a new #GstNavigation commands query. When executed, it will
227 * query the pipeline for the set of currently available commands.
229 * Returns: The new query.
233 gst_navigation_query_new_commands (void)
236 GstStructure *structure;
238 structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME,
239 "type", G_TYPE_STRING, "commands", NULL);
240 query = gst_query_new_application (GST_QUERY_CUSTOM, structure);
246 gst_query_list_add_command (GValue * list, GstNavigationCommand val)
248 GValue item = { 0, };
250 g_value_init (&item, GST_TYPE_NAVIGATION_COMMAND);
251 g_value_set_enum (&item, val);
252 gst_value_list_append_value (list, &item);
253 g_value_unset (&item);
257 * gst_navigation_query_set_commands:
258 * @query: a #GstQuery
259 * @n_cmds: the number of commands to set.
260 * @...: A list of @GstNavigationCommand values, @n_cmds entries long.
262 * Set the #GstNavigation command query result fields in @query. The number
263 * of commands passed must be equal to @n_commands.
268 gst_navigation_query_set_commands (GstQuery * query, gint n_cmds, ...)
271 GValue list = { 0, };
272 GstStructure *structure;
275 g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS));
277 g_value_init (&list, GST_TYPE_LIST);
279 va_start (ap, n_cmds);
280 for (i = 0; i < n_cmds; i++) {
281 GstNavigationCommand val = va_arg (ap, GstNavigationCommand);
282 gst_query_list_add_command (&list, val);
286 structure = gst_query_get_structure (query);
287 gst_structure_set_value (structure, "commands", &list);
289 g_value_unset (&list);
293 * gst_navigation_query_set_commandsv:
294 * @query: a #GstQuery
295 * @n_cmds: the number of commands to set.
296 * @cmds: An array containing @n_cmds @GstNavigationCommand values.
298 * Set the #GstNavigation command query result fields in @query. The number
299 * of commands passed must be equal to @n_commands.
304 gst_navigation_query_set_commandsv (GstQuery * query, gint n_cmds,
305 GstNavigationCommand * cmds)
307 GValue list = { 0, };
308 GstStructure *structure;
311 g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS));
313 g_value_init (&list, GST_TYPE_LIST);
314 for (i = 0; i < n_cmds; i++) {
315 gst_query_list_add_command (&list, cmds[i]);
317 structure = gst_query_get_structure (query);
318 gst_structure_set_value (structure, "commands", &list);
320 g_value_unset (&list);
324 * gst_navigation_query_parse_commands_length:
325 * @query: a #GstQuery
326 * @n_cmds: the number of commands in this query.
328 * Parse the number of commands in the #GstNavigation commands @query.
330 * Returns: %TRUE if the query could be successfully parsed. %FALSE if not.
334 gst_navigation_query_parse_commands_length (GstQuery * query, guint * n_cmds)
336 GstStructure *structure;
339 g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE);
344 structure = gst_query_get_structure (query);
345 list = gst_structure_get_value (structure, "commands");
349 *n_cmds = gst_value_list_get_size (list);
355 * gst_navigation_query_parse_commands_nth:
356 * @query: a #GstQuery
357 * @nth: the nth command to retrieve.
358 * @cmd: a pointer to store the nth command into.
360 * Parse the #GstNavigation command query and retrieve the @nth command from
361 * it into @cmd. If the list contains less elements than @nth, @cmd will be
362 * set to #GST_NAVIGATION_COMMAND_INVALID.
364 * Returns: %TRUE if the query could be successfully parsed. %FALSE if not.
368 gst_navigation_query_parse_commands_nth (GstQuery * query, guint nth,
369 GstNavigationCommand * cmd)
371 GstStructure *structure;
374 g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE);
379 structure = gst_query_get_structure (query);
380 list = gst_structure_get_value (structure, "commands");
382 *cmd = GST_NAVIGATION_COMMAND_INVALID;
384 if (nth < gst_value_list_get_size (list)) {
385 *cmd = (GstNavigationCommand)
386 g_value_get_enum (gst_value_list_get_value (list, nth));
388 *cmd = GST_NAVIGATION_COMMAND_INVALID;
395 * gst_navigation_query_new_angles:
397 * Create a new #GstNavigation angles query. When executed, it will
398 * query the pipeline for the set of currently available angles, which may be
399 * greater than one in a multiangle video.
401 * Returns: The new query.
405 gst_navigation_query_new_angles (void)
408 GstStructure *structure;
410 structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME,
411 "type", G_TYPE_STRING, "angles", NULL);
412 query = gst_query_new_application (GST_QUERY_CUSTOM, structure);
418 * gst_navigation_query_set_angles:
419 * @query: a #GstQuery
420 * @cur_angle: the current viewing angle to set.
421 * @n_angles: the number of viewing angles to set.
423 * Set the #GstNavigation angles query result field in @query.
428 gst_navigation_query_set_angles (GstQuery * query, guint cur_angle,
431 GstStructure *structure;
433 g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES));
435 structure = gst_query_get_structure (query);
436 gst_structure_set (structure,
437 "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL);
441 * gst_navigation_query_parse_angles:
442 * @query: a #GstQuery
443 * @cur_angle: Pointer to a #guint into which to store the currently selected
444 * angle value from the query, or NULL
445 * @n_angles: Pointer to a #guint into which to store the number of angles
446 * value from the query, or NULL
448 * Parse the current angle number in the #GstNavigation angles @query into the
449 * #guint pointed to by the @cur_angle variable, and the number of available
450 * angles into the #guint pointed to by the @n_angles variable.
452 * Returns: %TRUE if the query could be successfully parsed. %FALSE if not.
456 gst_navigation_query_parse_angles (GstQuery * query, guint * cur_angle,
459 GstStructure *structure;
462 g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES), FALSE);
464 structure = gst_query_get_structure (query);
467 ret &= gst_structure_get_uint (structure, "angle", cur_angle);
470 ret &= gst_structure_get_uint (structure, "angles", n_angles);
472 WARN_IF_FAIL (ret, "Couldn't extract details from angles query");
477 /* Navigation Messages */
479 #define GST_NAVIGATION_MESSAGE_HAS_TYPE(msg,msg_type) \
480 (gst_navigation_message_get_type (msg) == GST_NAVIGATION_MESSAGE_ ## msg_type)
483 * gst_navigation_message_get_type:
484 * @message: A #GstMessage to inspect.
486 * Check a bus message to see if it is a #GstNavigation event, and return
487 * the #GstNavigationMessageType identifying the type of the message if so.
489 * Returns: The type of the #GstMessage, or
490 * #GST_NAVIGATION_MESSAGE_INVALID if the message is not a #GstNavigation
495 GstNavigationMessageType
496 gst_navigation_message_get_type (GstMessage * message)
498 const GstStructure *s;
501 if (message == NULL || GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
502 return GST_NAVIGATION_MESSAGE_INVALID;
504 s = gst_message_get_structure (message);
505 if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_MESSAGE_NAME))
506 return GST_NAVIGATION_MESSAGE_INVALID;
508 m_type = gst_structure_get_string (s, "type");
510 return GST_NAVIGATION_MESSAGE_INVALID;
512 if (g_str_equal (m_type, "mouse-over"))
513 return GST_NAVIGATION_MESSAGE_MOUSE_OVER;
514 else if (g_str_equal (m_type, "commands-changed"))
515 return GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED;
516 else if (g_str_equal (m_type, "angles-changed"))
517 return GST_NAVIGATION_MESSAGE_ANGLES_CHANGED;
519 return GST_NAVIGATION_MESSAGE_INVALID;
523 * gst_navigation_message_new_mouse_over:
524 * @src: A #GstObject to set as source of the new message.
525 * @active: %TRUE if the mouse has entered a clickable area of the display.
526 * %FALSE if it over a non-clickable area.
528 * Creates a new #GstNavigation message with type
529 * #GST_NAVIGATION_MESSAGE_MOUSE_OVER.
531 * Returns: The new #GstMessage.
535 gst_navigation_message_new_mouse_over (GstObject * src, gboolean active)
540 s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME,
541 "type", G_TYPE_STRING, "mouse-over", "active", G_TYPE_BOOLEAN, active,
544 m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s);
550 * gst_navigation_message_parse_mouse_over:
551 * @message: A #GstMessage to inspect.
552 * @active: A pointer to a gboolean to receive the active/inactive state,
555 * Parse a #GstNavigation message of type #GST_NAVIGATION_MESSAGE_MOUSE_OVER
556 * and extract the active/inactive flag. If the mouse over event is marked
557 * active, it indicates that the mouse is over a clickable area.
559 * Returns: %TRUE if the message could be successfully parsed. %FALSE if not.
563 gst_navigation_message_parse_mouse_over (GstMessage * message,
566 if (!GST_NAVIGATION_MESSAGE_HAS_TYPE (message, MOUSE_OVER))
570 const GstStructure *s = gst_message_get_structure (message);
571 if (gst_structure_get_boolean (s, "active", active) == FALSE)
579 * gst_navigation_message_new_commands_changed:
580 * @src: A #GstObject to set as source of the new message.
582 * Creates a new #GstNavigation message with type
583 * #GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED
585 * Returns: The new #GstMessage.
589 gst_navigation_message_new_commands_changed (GstObject * src)
594 s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME,
595 "type", G_TYPE_STRING, "commands-changed", NULL);
597 m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s);
603 * gst_navigation_message_new_angles_changed:
604 * @src: A #GstObject to set as source of the new message.
605 * @cur_angle: The currently selected angle.
606 * @n_angles: The number of viewing angles now available.
608 * Creates a new #GstNavigation message with type
609 * #GST_NAVIGATION_MESSAGE_ANGLES_CHANGED for notifying an application
610 * that the current angle, or current number of angles available in a
611 * multiangle video has changed.
613 * Returns: The new #GstMessage.
617 gst_navigation_message_new_angles_changed (GstObject * src, guint cur_angle,
623 s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME,
624 "type", G_TYPE_STRING, "angles-changed",
625 "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL);
627 m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s);
633 * gst_navigation_message_parse_angles_changed:
634 * @message: A #GstMessage to inspect.
635 * @cur_angle: A pointer to a #guint to receive the new current angle number,
637 * @n_angles: A pointer to a #guint to receive the new angle count, or NULL.
639 * Parse a #GstNavigation message of type GST_NAVIGATION_MESSAGE_ANGLES_CHANGED
640 * and extract the @cur_angle and @n_angles parameters.
642 * Returns: %TRUE if the message could be successfully parsed. %FALSE if not.
646 gst_navigation_message_parse_angles_changed (GstMessage * message,
647 guint * cur_angle, guint * n_angles)
649 const GstStructure *s;
652 g_return_val_if_fail (GST_NAVIGATION_MESSAGE_HAS_TYPE (message,
653 ANGLES_CHANGED), FALSE);
655 s = gst_message_get_structure (message);
657 ret &= gst_structure_get_uint (s, "angle", cur_angle);
660 ret &= gst_structure_get_uint (s, "angles", n_angles);
662 WARN_IF_FAIL (ret, "Couldn't extract details from angles-changed event");
667 #define GST_NAVIGATION_EVENT_HAS_TYPE(event,event_type) \
668 (gst_navigation_event_get_type (event) == GST_NAVIGATION_EVENT_ ## event_type)
671 * gst_navigation_event_get_type:
672 * @event: A #GstEvent to inspect.
674 * Inspect a #GstEvent and return the #GstNavigationEventType of the event, or
675 * #GST_NAVIGATION_EVENT_INVALID if the event is not a #GstNavigation event.
679 GstNavigationEventType
680 gst_navigation_event_get_type (GstEvent * event)
682 const GstStructure *s;
685 if (event == NULL || GST_EVENT_TYPE (event) != GST_EVENT_NAVIGATION)
686 return GST_NAVIGATION_EVENT_INVALID;
688 s = gst_event_get_structure (event);
689 if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_EVENT_NAME))
690 return GST_NAVIGATION_EVENT_INVALID;
692 e_type = gst_structure_get_string (s, "event");
694 return GST_NAVIGATION_EVENT_INVALID;
696 if (g_str_equal (e_type, "mouse-button-press"))
697 return GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS;
698 else if (g_str_equal (e_type, "mouse-button-release"))
699 return GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE;
700 else if (g_str_equal (e_type, "mouse-move"))
701 return GST_NAVIGATION_EVENT_MOUSE_MOVE;
702 else if (g_str_equal (e_type, "key-press"))
703 return GST_NAVIGATION_EVENT_KEY_PRESS;
704 else if (g_str_equal (e_type, "key-release"))
705 return GST_NAVIGATION_EVENT_KEY_RELEASE;
706 else if (g_str_equal (e_type, "command"))
707 return GST_NAVIGATION_EVENT_COMMAND;
709 return GST_NAVIGATION_EVENT_INVALID;
713 * gst_navigation_event_parse_key_event:
714 * @event: A #GstEvent to inspect.
715 * @key: A pointer to a location to receive the string identifying the key
716 * press. The returned string is owned by the event, and valid only until the
722 gst_navigation_event_parse_key_event (GstEvent * event, const gchar ** key)
724 GstNavigationEventType e_type;
725 const GstStructure *s;
727 e_type = gst_navigation_event_get_type (event);
728 g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_KEY_PRESS ||
729 e_type == GST_NAVIGATION_EVENT_KEY_RELEASE, FALSE);
732 s = gst_event_get_structure (event);
733 *key = gst_structure_get_string (s, "key");
742 * gst_navigation_event_parse_mouse_button_event:
743 * @event: A #GstEvent to inspect.
744 * @button: Pointer to a gint that will receive the button number associated
746 * @x: Pointer to a gdouble to receive the x coordinate of the mouse button
748 * @y: Pointer to a gdouble to receive the y coordinate of the mouse button
751 * Retrieve the details of either a #GstNavigation mouse button press event or
752 * a mouse button release event. Determine which type the event is using
753 * gst_navigation_event_get_type() to retrieve the #GstNavigationEventType.
755 * Returns: TRUE if the button number and both coordinates could be extracted,
761 gst_navigation_event_parse_mouse_button_event (GstEvent * event, gint * button,
762 gdouble * x, gdouble * y)
764 GstNavigationEventType e_type;
765 const GstStructure *s;
768 e_type = gst_navigation_event_get_type (event);
769 g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS ||
770 e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE, FALSE);
772 s = gst_event_get_structure (event);
774 ret &= gst_structure_get_double (s, "pointer_x", x);
776 ret &= gst_structure_get_double (s, "pointer_y", y);
778 ret &= gst_structure_get_int (s, "button", button);
780 WARN_IF_FAIL (ret, "Couldn't extract details from mouse button event");
786 * gst_navigation_event_parse_mouse_move_event:
787 * @event: A #GstEvent to inspect.
788 * @x: Pointer to a gdouble to receive the x coordinate of the mouse movement.
789 * @y: Pointer to a gdouble to receive the y coordinate of the mouse movement.
791 * Inspect a #GstNavigation mouse movement event and extract the coordinates
794 * Returns: TRUE if both coordinates could be extracted, otherwise FALSE.
799 gst_navigation_event_parse_mouse_move_event (GstEvent * event, gdouble * x,
802 const GstStructure *s;
805 g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, MOUSE_MOVE),
808 s = gst_event_get_structure (event);
810 ret &= gst_structure_get_double (s, "pointer_x", x);
812 ret &= gst_structure_get_double (s, "pointer_y", y);
814 WARN_IF_FAIL (ret, "Couldn't extract positions from mouse move event");
820 * gst_navigation_event_parse_command:
821 * @event: A #GstEvent to inspect.
822 * @command: Pointer to GstNavigationCommand to receive the type of the
825 * Inspect a #GstNavigation command event and retrieve the enum value of the
826 * associated command.
828 * Returns: TRUE if the navigation command could be extracted, otherwise FALSE.
833 gst_navigation_event_parse_command (GstEvent * event,
834 GstNavigationCommand * command)
836 const GstStructure *s;
839 g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, COMMAND), FALSE);
842 s = gst_event_get_structure (event);
843 ret = gst_structure_get_uint (s, "command-code", (guint *) command);
844 WARN_IF_FAIL (ret, "Couldn't extract command code from command event");