diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt index 340cffce72..15d2a9c5f1 100644 --- a/docs/libs/gst-plugins-base-libs-sections.txt +++ b/docs/libs/gst-plugins-base-libs-sections.txt @@ -506,16 +506,50 @@ gst_mixer_track_get_type gst/interfaces/navigation.h GstNavigation GstNavigationInterface +GstNavigationCommand +GstNavigationMessageType +GstNavigationQueryType gst_navigation_send_event gst_navigation_send_key_event gst_navigation_send_mouse_event +gst_navigation_send_command + +gst_navigation_message_get_type +gst_navigation_message_new_angles_changed +gst_navigation_message_new_commands_changed +gst_navigation_message_new_mouse_over +gst_navigation_message_parse_mouse_over +gst_navigation_query_new_angles +gst_navigation_query_get_type +gst_navigation_query_new_commands +gst_navigation_query_parse_angles +gst_navigation_query_parse_commands_length +gst_navigation_query_parse_commands_nth +gst_navigation_query_set_angles +gst_navigation_query_set_commands +gst_navigation_query_set_commandsv + +GST_NAVIGATION_COMMAND_DVD_ANGLE_MENU +GST_NAVIGATION_COMMAND_DVD_AUDIO_MENU +GST_NAVIGATION_COMMAND_DVD_CHAPTER_MENU +GST_NAVIGATION_COMMAND_DVD_MENU +GST_NAVIGATION_COMMAND_DVD_ROOT_MENU +GST_NAVIGATION_COMMAND_DVD_SUBPICTURE_MENU +GST_NAVIGATION_COMMAND_DVD_TITLE_MENU + GST_TYPE_NAVIGATION GST_NAVIGATION GST_NAVIGATION_GET_IFACE +GST_TYPE_NAVIGATION_COMMAND +GST_TYPE_NAVIGATION_MESSAGE_TYPE +GST_TYPE_NAVIGATION_QUERY_TYPE GST_IS_NAVIGATION gst_navigation_get_type +gst_navigation_message_type_get_type +gst_navigation_query_type_get_type +gst_navigation_command_get_type
diff --git a/gst-libs/gst/interfaces/navigation.c b/gst-libs/gst/interfaces/navigation.c index cd1f844336..892ee75323 100644 --- a/gst-libs/gst/interfaces/navigation.c +++ b/gst-libs/gst/interfaces/navigation.c @@ -24,9 +24,14 @@ #endif #include +#include 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" + GType gst_navigation_get_type (void) { @@ -71,21 +76,714 @@ gst_navigation_send_event (GstNavigation * navigation, GstStructure * structure) } } +/** + * gst_navigation_send_mouse_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) { gst_navigation_send_event (navigation, - gst_structure_new ("application/x-gst-navigation", "event", G_TYPE_STRING, + 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) { gst_navigation_send_event (navigation, - gst_structure_new ("application/x-gst-navigation", "event", G_TYPE_STRING, + 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. + * + * Since: 0.10.23 + */ +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 + * Since: 0.10.23 + */ +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. + * Since: 0.10.23 + */ +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_application (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. + * + * Since: 0.10.23 + */ +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_get_structure (query); + gst_structure_set_value (structure, "commands", &list); + + g_value_unset (&list); +} + +/** + * gst_navigation_query_set_commandsv: + * @query: a #GstQuery + * @n_cmds: the number of commands to set. + * @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. + * + * Since: 0.10.23 + */ +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_get_structure (query); + gst_structure_set_value (structure, "commands", &list); + + g_value_unset (&list); +} + +/** + * gst_navigation_query_parse_commands_length: + * @query: a #GstQuery + * @n_cmds: 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. + * Since: 0.10.23 + */ +gboolean +gst_navigation_query_parse_commands_length (GstQuery * query, guint * n_cmds) +{ + 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: 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. + * Since: 0.10.23 + */ +gboolean +gst_navigation_query_parse_commands_nth (GstQuery * query, guint nth, + GstNavigationCommand * cmd) +{ + 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. + * Since: 0.10.23 + */ +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_application (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. + * + * Since: 0.10.23 + */ +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_get_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: Pointer to a #guint into which to store the currently selected + * angle value from the query, or NULL + * @n_angles: 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. + * Since: 0.10.23 + */ +gboolean +gst_navigation_query_parse_angles (GstQuery * query, guint * cur_angle, + guint * n_angles) +{ + GstStructure *structure; + + g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES), FALSE); + + structure = gst_query_get_structure (query); + + if (cur_angle) + g_return_val_if_fail (gst_structure_get_uint (structure, + "angle", cur_angle), FALSE); + + if (n_angles) + g_return_val_if_fail (gst_structure_get_uint (structure, + "angles", n_angles), FALSE); + + return TRUE; +} + +/* 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 #GstNavigationMessage, or + * #GST_NAVIGATION_MESSAGE_INVALID if the message is not a #GstNavigation + * notification. + * + * Since: 0.10.23 + */ +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; + + 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. + * Since: 0.10.23 + */ +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: 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. + * Since: 0.10.23 + */ +gboolean +gst_navigation_message_parse_mouse_over (GstMessage * message, + gboolean * active) +{ + g_return_val_if_fail (GST_NAVIGATION_MESSAGE_HAS_TYPE (message, MOUSE_OVER), + FALSE); + + if (active) { + const GstStructure *s = gst_message_get_structure (message); + g_return_val_if_fail (gst_structure_get_boolean (s, "active", active), + 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. + * Since: 0.10.23 + */ +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. + * Since: 0.10.23 + */ +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: A pointer to a #guint to receive the new current angle number, + * or NULL + * @n_angles: 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. + * Since: 0.10.23 + */ +gboolean +gst_navigation_message_parse_angles_changed (GstMessage * message, + guint * cur_angle, guint * n_angles) +{ + const GstStructure *s; + + g_return_val_if_fail (GST_NAVIGATION_MESSAGE_HAS_TYPE (message, + ANGLES_CHANGED), FALSE); + + s = gst_message_get_structure (message); + if (cur_angle) + g_return_val_if_fail (gst_structure_get_uint (s, "angle", cur_angle), + FALSE); + + if (n_angles) + g_return_val_if_fail (gst_structure_get_uint (s, "angles", n_angles), + FALSE); + + return TRUE; +} + +#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. + * + * Since: 0.10.23 + */ +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: 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. + * + * Since: 0.10.23 + */ +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: Pointer to a gint that will receive the button number associated + * with the event. + * @x: Pointer to a gdouble to receive the x coordinate of the mouse button + * event. + * @y: 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. + * + * Since: 0.10.23 + */ +gboolean +gst_navigation_event_parse_mouse_button_event (GstEvent * event, gint * button, + gdouble * x, gdouble * y) +{ + GstNavigationEventType e_type; + const GstStructure *s; + + 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) + g_return_val_if_fail (gst_structure_get_double (s, "pointer_x", x), FALSE); + if (y) + g_return_val_if_fail (gst_structure_get_double (s, "pointer_y", y), FALSE); + if (button) + g_return_val_if_fail (gst_structure_get_int (s, "button", button), FALSE); + + return TRUE; +} + +/** + * gst_navigation_event_parse_mouse_move_event: + * @event: A #GstEvent to inspect. + * @x: Pointer to a gdouble to receive the x coordinate of the mouse movement. + * @y: 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. + * + * Since: 0.10.23 + */ +gboolean +gst_navigation_event_parse_mouse_move_event (GstEvent * event, gdouble * x, + gdouble * y) +{ + const GstStructure *s; + + g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, MOUSE_MOVE), + FALSE); + + s = gst_event_get_structure (event); + if (x) + g_return_val_if_fail (gst_structure_get_double (s, "pointer_x", x), FALSE); + if (y) + g_return_val_if_fail (gst_structure_get_double (s, "pointer_y", y), FALSE); + + return TRUE; +} + +/** + * gst_navigation_event_parse_command: + * @event: A #GstEvent to inspect. + * @command: 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. + * + * Since: 0.10.23 + */ +gboolean +gst_navigation_event_parse_command (GstEvent * event, + GstNavigationCommand * command) +{ + const GstStructure *s; + g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, COMMAND), FALSE); + + if (command) { + s = gst_event_get_structure (event); + g_return_val_if_fail (gst_structure_get_uint (s, "command-code", command), + FALSE); + } + + return TRUE; +} diff --git a/gst-libs/gst/interfaces/navigation.h b/gst-libs/gst/interfaces/navigation.h index b67130a10c..33bf4629d9 100644 --- a/gst-libs/gst/interfaces/navigation.h +++ b/gst-libs/gst/interfaces/navigation.h @@ -49,13 +49,207 @@ typedef struct _GstNavigationInterface { GType gst_navigation_get_type (void); -/* virtual class function wrappers */ -void gst_navigation_send_event (GstNavigation *navigation, GstStructure *structure); +/* Navigation commands */ +/** + * GstNavigationCommand: + * @GST_NAVIGATION_COMMAND_INVALID: An invalid command entry + * @GST_NAVIGATION_COMMAND_MENU1: Execute navigation menu command 1. For DVD, + * this enters the DVD root menu, or exits back to the title from the menu. + * @GST_NAVIGATION_COMMAND_MENU2: Execute navigation menu command 2. For DVD, + * this jumps to the DVD title menu. + * @GST_NAVIGATION_COMMAND_MENU3: Execute navigation menu command 3. For DVD, + * this jumps into the DVD root menu. + * @GST_NAVIGATION_COMMAND_MENU4: Execute navigation menu command 4. For DVD, + * this jumps to the Subpicture menu. + * @GST_NAVIGATION_COMMAND_MENU5: Execute navigation menu command 5. For DVD, + * the jumps to the audio menu. + * @GST_NAVIGATION_COMMAND_MENU6: Execute navigation menu command 6. For DVD, + * this jumps to the angles menu. + * @GST_NAVIGATION_COMMAND_MENU7: Execute navigation menu command 7. For DVD, + * this jumps to the chapter menu. + * @GST_NAVIGATION_COMMAND_LEFT: Select the next button to the left in a menu, + * if such a button exists. + * @GST_NAVIGATION_COMMAND_RIGHT: Select the next button to the right in a menu, + * if such a button exists. + * @GST_NAVIGATION_COMMAND_UP: Select the button above the current one in a + * menu, if such a button exists. + * @GST_NAVIGATION_COMMAND_DOWN: Select the button below the current one in a + * menu, if such a button exists. + * @GST_NAVIGATION_COMMAND_ACTIVATE: Activate (click) the currently selected + * button in a menu, if such a button exists. + * @GST_NAVIGATION_COMMAND_PREV_ANGLE: Switch to the previous angle in a + * multiangle feature. + * @GST_NAVIGATION_COMMAND_NEXT_ANGLE: Switch to the next angle in a multiangle + * feature. + * + * A set of commands that may be issued to an element providing the + * #GstNavigation interface. The available commands can be queried via + * the gst_navigation_query_new_commands() query. + * + * For convenience in handling DVD navigation, the MENU commands are aliased as: + * GST_NAVIGATION_COMMAND_DVD_MENU = @GST_NAVIGATION_COMMAND_MENU1 + * GST_NAVIGATION_COMMAND_DVD_TITLE_MENU = @GST_NAVIGATION_COMMAND_MENU2 + * GST_NAVIGATION_COMMAND_DVD_ROOT_MENU = @GST_NAVIGATION_COMMAND_MENU3 + * GST_NAVIGATION_COMMAND_DVD_SUBPICTURE_MENU = @GST_NAVIGATION_COMMAND_MENU4 + * GST_NAVIGATION_COMMAND_DVD_AUDIO_MENU = @GST_NAVIGATION_COMMAND_MENU5 + * GST_NAVIGATION_COMMAND_DVD_ANGLE_MENU = @GST_NAVIGATION_COMMAND_MENU6 + * GST_NAVIGATION_COMMAND_DVD_CHAPTER_MENU = @GST_NAVIGATION_COMMAND_MENU7 + * + * Since: 0.10.23 + */ +typedef enum { + GST_NAVIGATION_COMMAND_INVALID = 0, + + GST_NAVIGATION_COMMAND_MENU1 = 1, + GST_NAVIGATION_COMMAND_MENU2 = 2, + GST_NAVIGATION_COMMAND_MENU3 = 3, + GST_NAVIGATION_COMMAND_MENU4 = 4, + GST_NAVIGATION_COMMAND_MENU5 = 5, + GST_NAVIGATION_COMMAND_MENU6 = 6, + GST_NAVIGATION_COMMAND_MENU7 = 7, + + GST_NAVIGATION_COMMAND_LEFT = 20, + GST_NAVIGATION_COMMAND_RIGHT = 21, + GST_NAVIGATION_COMMAND_UP = 22, + GST_NAVIGATION_COMMAND_DOWN = 23, + GST_NAVIGATION_COMMAND_ACTIVATE = 24, + + GST_NAVIGATION_COMMAND_PREV_ANGLE = 30, + GST_NAVIGATION_COMMAND_NEXT_ANGLE = 31 +} GstNavigationCommand; + +/* Some aliases for the menu command types */ +#define GST_NAVIGATION_COMMAND_DVD_MENU GST_NAVIGATION_COMMAND_MENU1 +#define GST_NAVIGATION_COMMAND_DVD_TITLE_MENU GST_NAVIGATION_COMMAND_MENU2 +#define GST_NAVIGATION_COMMAND_DVD_ROOT_MENU GST_NAVIGATION_COMMAND_MENU3 +#define GST_NAVIGATION_COMMAND_DVD_SUBPICTURE_MENU GST_NAVIGATION_COMMAND_MENU4 +#define GST_NAVIGATION_COMMAND_DVD_AUDIO_MENU GST_NAVIGATION_COMMAND_MENU5 +#define GST_NAVIGATION_COMMAND_DVD_ANGLE_MENU GST_NAVIGATION_COMMAND_MENU6 +#define GST_NAVIGATION_COMMAND_DVD_CHAPTER_MENU GST_NAVIGATION_COMMAND_MENU7 + +/* Queries */ +typedef enum +{ + GST_NAVIGATION_QUERY_INVALID = 0, + GST_NAVIGATION_QUERY_COMMANDS = 1, + GST_NAVIGATION_QUERY_ANGLES = 2 +} GstNavigationQueryType; + +GstNavigationQueryType gst_navigation_query_get_type (GstQuery *query); + +GstQuery *gst_navigation_query_new_commands (void); +void gst_navigation_query_set_commands (GstQuery *query, gint n_cmds, ...); +void gst_navigation_query_set_commandsv (GstQuery *query, gint n_cmds, + GstNavigationCommand *cmds); +gboolean gst_navigation_query_parse_commands_length (GstQuery *query, + guint *n_cmds); +gboolean gst_navigation_query_parse_commands_nth (GstQuery *query, guint nth, + GstNavigationCommand *cmd); + +GstQuery *gst_navigation_query_new_angles (void); +void gst_navigation_query_set_angles (GstQuery *query, guint cur_angle, + guint n_angles); +gboolean gst_navigation_query_parse_angles (GstQuery *query, guint *cur_angle, + guint *n_angles); + +/* Element messages */ +/** + * GstNavigationMessageType: + * @GST_NAVIGATION_MESSAGE_INVALID: Returned from + * gst_navigation_message_get_type() when the passed message is not a + * navigation message. + * @GST_NAVIGATION_MESSAGE_MOUSE_OVER: Sent when the mouse moves over or leaves a + * clickable region of the output, such as a DVD menu button. + * @GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED: Sent when the set of available commands + * changes and should re-queried by interested applications. + * @GST_NAVIGATION_MESSAGE_ANGLES_CHANGED: Sent when display angles in a multi-angle + * feature (such as a multiangle DVD) change - either angles have appeared or + * disappeared. + * + * A set of notifications that may be received on the bus when navigation + * related status changes. + * + * Since: 0.10.23 + */ +typedef enum { + GST_NAVIGATION_MESSAGE_INVALID, + GST_NAVIGATION_MESSAGE_MOUSE_OVER, + GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED, + GST_NAVIGATION_MESSAGE_ANGLES_CHANGED +} GstNavigationMessageType; + +GstNavigationMessageType gst_navigation_message_get_type (GstMessage *message); + +GstMessage *gst_navigation_message_new_mouse_over (GstObject *src, + gboolean active); +gboolean gst_navigation_message_parse_mouse_over (GstMessage *message, + gboolean *active); + +GstMessage *gst_navigation_message_new_commands_changed (GstObject *src); + +GstMessage *gst_navigation_message_new_angles_changed (GstObject *src, + guint cur_angle, + guint n_angles); +gboolean gst_navigation_message_parse_angles_changed (GstMessage *message, + guint *cur_angle, + guint *n_angles); + +/* event parsing functions */ +/** + * GstNavigationEventType: + * @GST_NAVIGATION_EVENT_INVALID: Returned from + * gst_navigation_event_get_type() when the passed event is not a navigation event. + * @GST_NAVIGATION_EVENT_KEY_PRESS: A key press event. Use + * gst_navigation_event_parse_key_event() to extract the details from the event. + * @GST_NAVIGATION_EVENT_KEY_RELEASE: A key release event. Use + * gst_navigation_event_parse_key_event() to extract the details from the event. + * @GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS: A mouse button press event. Use + * gst_navigation_event_parse_mouse_button_event() to extract the details from the + * event. + * @GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE: A mouse button release event. Use + * gst_navigation_event_parse_mouse_button_event() to extract the details from the + * event. + * @GST_NAVIGATION_EVENT_MOUSE_MOVE: A mouse movement event. Use + * gst_navigation_event_parse_mouse_move_event() to extract the details from the + * event. + * @GST_NAVIGATION_EVENT_COMMAND: A navigation command event. Use + * gst_navigation_event_parse_command() to extract the details from the event. + * + * Enum values for the various events that an element implementing the + * GstNavigation interface might send up the pipeline. + * + * Since: 0.10.23 + */ +typedef enum { + GST_NAVIGATION_EVENT_INVALID = 0, + GST_NAVIGATION_EVENT_KEY_PRESS = 1, + GST_NAVIGATION_EVENT_KEY_RELEASE = 2, + GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS = 3, + GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE = 4, + GST_NAVIGATION_EVENT_MOUSE_MOVE = 5, + GST_NAVIGATION_EVENT_COMMAND = 6 +} GstNavigationEventType; + +GstNavigationEventType gst_navigation_event_get_type (GstEvent *event); +gboolean gst_navigation_event_parse_key_event (GstEvent *event, + const gchar **key); +gboolean gst_navigation_event_parse_mouse_button_event (GstEvent *event, + gint *button, gdouble *x, gdouble *y); +gboolean gst_navigation_event_parse_mouse_move_event (GstEvent *event, + gdouble *x, gdouble *y); +gboolean gst_navigation_event_parse_command (GstEvent *event, + GstNavigationCommand *command); + +/* interface virtual function wrappers */ +void gst_navigation_send_event (GstNavigation *navigation, + GstStructure *structure); void gst_navigation_send_key_event (GstNavigation *navigation, const char *event, const char *key); void gst_navigation_send_mouse_event (GstNavigation *navigation, const char *event, int button, double x, double y); +void gst_navigation_send_command (GstNavigation *navigation, + GstNavigationCommand command); G_END_DECLS diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 60e8f6a350..f6d1b24179 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -112,6 +112,7 @@ check_PROGRAMS = \ libs/cddabasesrc \ libs/fft \ libs/mixer \ + libs/navigation \ libs/netbuffer \ libs/pbutils \ libs/rtp \ @@ -181,6 +182,16 @@ libs_mixer_LDADD = \ $(GST_BASE_LIBS) \ $(LDADD) +libs_navigation_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_navigation_LDADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + libs_netbuffer_CFLAGS = \ $(GST_PLUGINS_BASE_CFLAGS) \ $(AM_CFLAGS) diff --git a/tests/check/libs/.gitignore b/tests/check/libs/.gitignore index d57728a1ec..cd372588c4 100644 --- a/tests/check/libs/.gitignore +++ b/tests/check/libs/.gitignore @@ -3,6 +3,7 @@ audio cddabasesrc fft mixer +navigation netbuffer pbutils rtp diff --git a/tests/check/libs/navigation.c b/tests/check/libs/navigation.c new file mode 100644 index 0000000000..4712947b80 --- /dev/null +++ b/tests/check/libs/navigation.c @@ -0,0 +1,351 @@ +/* GStreamer + * + * unit tests for the navigation interface library + * + * Copyright (C) 2009 Jan Schmidt + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include + +#define TEST_ELEMENT_TYPE (test_element_get_type()) + +typedef struct TestElement TestElement; +typedef struct TestElementClass TestElementClass; + +struct TestElement +{ + GstElement parent; + + GstNavigationEventType sent_type; + const gchar *sent_key; + gdouble sent_x, sent_y; + gint sent_button; + GstNavigationCommand sent_command; +}; + +struct TestElementClass +{ + GstElementClass parent_class; +}; + +static void init_interface (GType type); +static void gst_implements_interface_init (GstImplementsInterfaceClass * klass); +static void nav_send_event (GstNavigation * navigation, + GstStructure * structure); + +GST_BOILERPLATE_FULL (TestElement, test_element, GstElement, GST_TYPE_ELEMENT, + init_interface); + +static void +test_element_navigation_interface_init (GstNavigationInterface * klass) +{ + klass->send_event = nav_send_event; +} + +static void +init_interface (GType type) +{ + static const GInterfaceInfo navigation_iface_info = { + (GInterfaceInitFunc) test_element_navigation_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo implements_iface_info = { + (GInterfaceInitFunc) gst_implements_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, + &implements_iface_info); + g_type_add_interface_static (type, GST_TYPE_NAVIGATION, + &navigation_iface_info); +} + +static void +test_element_base_init (gpointer klass) +{ +} + +static void +test_element_class_init (TestElementClass * klass) +{ +} + +static gboolean +test_element_interface_supported (GstImplementsInterface * ifacE, + GType interface_type) +{ + if (interface_type == GST_TYPE_NAVIGATION) + return TRUE; + + return FALSE; +} + +static void +gst_implements_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = test_element_interface_supported; +} + +static void +test_element_init (TestElement * this, TestElementClass * klass) +{ +} + +static void +nav_send_event (GstNavigation * navigation, GstStructure * structure) +{ + GstEvent *event = gst_event_new_navigation (structure); + GstNavigationEventType etype = gst_navigation_event_get_type (event); + TestElement *self = (TestElement *) (navigation); + + fail_if (etype == GST_NAVIGATION_EVENT_INVALID, + "Received navigation event could not be parsed"); + fail_unless (etype == self->sent_type, + "Received navigation event did not match sent"); + + switch (etype) { + case GST_NAVIGATION_EVENT_KEY_PRESS: + case GST_NAVIGATION_EVENT_KEY_RELEASE:{ + const gchar *key; + fail_unless (gst_navigation_event_parse_key_event (event, &key)); + fail_unless (strcmp (key, self->sent_key) == 0); + break; + } + case GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS: + case GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE:{ + gint button; + gdouble x, y; + fail_unless (gst_navigation_event_parse_mouse_button_event (event, + &button, &x, &y)); + fail_unless (button == self->sent_button); + fail_unless (x == self->sent_x); + fail_unless (y == self->sent_y); + break; + } + case GST_NAVIGATION_EVENT_MOUSE_MOVE:{ + gdouble x, y; + fail_unless (gst_navigation_event_parse_mouse_move_event (event, &x, &y)); + fail_unless (x == self->sent_x); + fail_unless (y == self->sent_y); + break; + } + case GST_NAVIGATION_EVENT_COMMAND:{ + GstNavigationCommand cmd; + fail_unless (gst_navigation_event_parse_command (event, &cmd)); + fail_unless (cmd == self->sent_command); + } + default: + break; + } + + gst_event_unref (event); +} + +GST_START_TEST (test_events) +{ + /* Create an empty GstElement that has a GstNavigation interface and then + * send some navigation events and validate them */ + TestElement *test_element = + (TestElement *) g_object_new (TEST_ELEMENT_TYPE, NULL); + GstNavigationCommand cmds[] = { + GST_NAVIGATION_COMMAND_MENU1, GST_NAVIGATION_COMMAND_MENU2, + GST_NAVIGATION_COMMAND_MENU3, GST_NAVIGATION_COMMAND_MENU4, + GST_NAVIGATION_COMMAND_MENU5, GST_NAVIGATION_COMMAND_MENU6, + GST_NAVIGATION_COMMAND_MENU7, GST_NAVIGATION_COMMAND_LEFT, + GST_NAVIGATION_COMMAND_RIGHT, GST_NAVIGATION_COMMAND_UP, + GST_NAVIGATION_COMMAND_DOWN, GST_NAVIGATION_COMMAND_ACTIVATE, + GST_NAVIGATION_COMMAND_PREV_ANGLE, GST_NAVIGATION_COMMAND_NEXT_ANGLE + }; + gint i; + + test_element->sent_type = GST_NAVIGATION_EVENT_KEY_PRESS; + test_element->sent_key = "1"; + gst_navigation_send_key_event (GST_NAVIGATION (test_element), "key-press", + "1"); + + test_element->sent_type = GST_NAVIGATION_EVENT_KEY_RELEASE; + test_element->sent_key = "2"; + gst_navigation_send_key_event (GST_NAVIGATION (test_element), "key-release", + "2"); + + test_element->sent_type = GST_NAVIGATION_EVENT_MOUSE_MOVE; + test_element->sent_x = 50; + test_element->sent_y = 100; + gst_navigation_send_mouse_event (GST_NAVIGATION (test_element), "mouse-move", + 0, 50, 100); + + test_element->sent_type = GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS; + test_element->sent_x = 10; + test_element->sent_y = 20; + test_element->sent_button = 1; + gst_navigation_send_mouse_event (GST_NAVIGATION (test_element), + "mouse-button-press", 1, 10, 20); + + for (i = 0; i < G_N_ELEMENTS (cmds); i++) { + test_element->sent_type = GST_NAVIGATION_EVENT_COMMAND; + test_element->sent_command = cmds[i]; + gst_navigation_send_command (GST_NAVIGATION (test_element), cmds[i]); + } + + gst_object_unref (test_element); +} + +GST_END_TEST; + +GST_START_TEST (test_messages) +{ + GstMessage *m; + /* GST_NAVIGATION_MESSAGE_MOUSE_OVER */ + { + gboolean active; + m = gst_navigation_message_new_mouse_over (NULL, TRUE); + fail_if (m == NULL); + fail_unless (gst_navigation_message_get_type (m) == + GST_NAVIGATION_MESSAGE_MOUSE_OVER); + fail_unless (GST_MESSAGE_SRC (m) == NULL); + fail_unless (gst_navigation_message_parse_mouse_over (m, &active)); + fail_unless (active == TRUE); + gst_message_unref (m); + + m = gst_navigation_message_new_mouse_over (NULL, FALSE); + fail_if (m == NULL); + fail_unless (GST_MESSAGE_SRC (m) == NULL); + fail_unless (gst_navigation_message_get_type (m) == + GST_NAVIGATION_MESSAGE_MOUSE_OVER); + fail_unless (gst_navigation_message_parse_mouse_over (m, &active)); + fail_unless (active == FALSE); + gst_message_unref (m); + } + + /* GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED */ + { + m = gst_navigation_message_new_commands_changed (NULL); + fail_if (m == NULL); + fail_unless (GST_MESSAGE_SRC (m) == NULL); + fail_unless (gst_navigation_message_get_type (m) == + GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED); + gst_message_unref (m); + } + + /* GST_NAVIGATION_MESSAGE_ANGLES_CHANGED */ + { + guint angle, angles; + m = gst_navigation_message_new_angles_changed (NULL, 1, 5); + fail_if (m == NULL); + fail_unless (GST_MESSAGE_SRC (m) == NULL); + fail_unless (gst_navigation_message_get_type (m) == + GST_NAVIGATION_MESSAGE_ANGLES_CHANGED); + fail_unless (gst_navigation_message_parse_angles_changed (m, &angle, + &angles)); + fail_unless (angle == 1); + fail_unless (angles == 5); + gst_message_unref (m); + } +} + +GST_END_TEST; + +GST_START_TEST (test_queries) +{ + GstQuery *q; + + /* GST_NAVIGATION_QUERY_COMMANDS */ + { + guint n; + GstNavigationCommand cmd; + + q = gst_navigation_query_new_commands (); + fail_unless (q != NULL); + fail_unless (gst_navigation_query_get_type (q) == + GST_NAVIGATION_QUERY_COMMANDS); + gst_navigation_query_set_commands (q, 3, GST_NAVIGATION_COMMAND_LEFT, + GST_NAVIGATION_COMMAND_MENU1, GST_NAVIGATION_COMMAND_MENU5); + fail_unless (gst_navigation_query_parse_commands_length (q, &n)); + fail_unless (n == 3); + fail_unless (gst_navigation_query_parse_commands_nth (q, 1, &cmd)); + fail_unless (cmd == GST_NAVIGATION_COMMAND_MENU1); + + fail_unless (gst_navigation_query_parse_commands_length (q, NULL)); + fail_unless (gst_navigation_query_parse_commands_nth (q, 2, NULL)); + + gst_query_unref (q); + } + + /* GST_NAVIGATION_QUERY_ANGLES */ + { + guint angle, angles; + q = gst_navigation_query_new_angles (); + fail_unless (q != NULL); + fail_unless (gst_navigation_query_get_type (q) == + GST_NAVIGATION_QUERY_ANGLES); + gst_navigation_query_set_angles (q, 4, 8); + fail_unless (gst_navigation_query_parse_angles (q, &angle, &angles)); + fail_unless (angle == 4); + fail_unless (angles == 8); + + fail_unless (gst_navigation_query_parse_angles (q, NULL, &angles)); + fail_unless (gst_navigation_query_parse_angles (q, &angle, NULL)); + fail_unless (gst_navigation_query_parse_angles (q, NULL, NULL)); + + gst_query_unref (q); + } + +} + +GST_END_TEST; + +static Suite * +navigation_suite (void) +{ + Suite *s = suite_create ("navigation interface"); + TCase *tc_chain = tcase_create ("notifications"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_events); + tcase_add_test (tc_chain, test_messages); + tcase_add_test (tc_chain, test_queries); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = navigation_suite (); + SRunner *sr = srunner_create (s); + + gst_check_init (&argc, &argv); + + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed (sr); + srunner_free (sr); + + return nf; +} diff --git a/win32/common/libgstinterfaces.def b/win32/common/libgstinterfaces.def index a034b97610..1e7009d9b5 100644 --- a/win32/common/libgstinterfaces.def +++ b/win32/common/libgstinterfaces.def @@ -34,7 +34,32 @@ EXPORTS gst_mixer_track_get_type gst_mixer_type_get_type gst_mixer_volume_changed + gst_navigation_command_get_type + gst_navigation_event_get_type + gst_navigation_event_parse_command + gst_navigation_event_parse_key_event + gst_navigation_event_parse_mouse_button_event + gst_navigation_event_parse_mouse_move_event + gst_navigation_event_type_get_type gst_navigation_get_type + gst_navigation_message_get_type + gst_navigation_message_new_angles_changed + gst_navigation_message_new_commands_changed + gst_navigation_message_new_mouse_over + gst_navigation_message_parse_angles_changed + gst_navigation_message_parse_mouse_over + gst_navigation_message_type_get_type + gst_navigation_query_get_type + gst_navigation_query_new_angles + gst_navigation_query_new_commands + gst_navigation_query_parse_angles + gst_navigation_query_parse_commands_length + gst_navigation_query_parse_commands_nth + gst_navigation_query_set_angles + gst_navigation_query_set_commands + gst_navigation_query_set_commandsv + gst_navigation_query_type_get_type + gst_navigation_send_command gst_navigation_send_event gst_navigation_send_key_event gst_navigation_send_mouse_event