gst_plugins_base/gst-libs/gst/interfaces/navigation.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /* GStreamer Navigation
     1 /* GStreamer Navigation
     2  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
     2  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
     3  * Copyright (C) 2007-2009 Jan Schmidt <thaytan@noraisin.net>
       
     4  *
     3  *
     5  * navigation.c: navigation event virtual class function wrappers
     4  * navigation.c: navigation design virtual class function wrappers
     6  *
     5  *
     7  * This library is free software; you can redistribute it and/or
     6  * This library is free software; you can redistribute it and/or
     8  * modify it under the terms of the GNU Library General Public
     7  * modify it under the terms of the GNU Library General Public
     9  * License as published by the Free Software Foundation; either
     8  * License as published by the Free Software Foundation; either
    10  * version 2 of the License, or (at your option) any later version.
     9  * version 2 of the License, or (at your option) any later version.
    18  * License along with this library; if not, write to the
    17  * License along with this library; if not, write to the
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    20  * Boston, MA 02111-1307, USA.
    19  * Boston, MA 02111-1307, USA.
    21  */
    20  */
    22 
    21 
    23 /**
       
    24  * SECTION:gstnavigation
       
    25  * @short_description: Interface for creating, sending and parsing navigation
       
    26  * events.
       
    27  *
       
    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.
       
    32  *
       
    33  * The main parts of the API are:
       
    34  * <itemizedlist>
       
    35  * <listitem>
       
    36  * <para>
       
    37  * The GstNavigation interface, implemented by elements which provide an application
       
    38  * with the ability to create and inject navigation events into the pipeline.
       
    39  * </para>
       
    40  * </listitem>
       
    41  * <listitem>
       
    42  * <para>
       
    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
       
    46  * messages.
       
    47  * </para>
       
    48  * </listitem>
       
    49  * <listitem>
       
    50  * <para>
       
    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.
       
    54  * </para><para>
       
    55  * The GstNavigation message functions provide functions for creating and parsing
       
    56  * custom bus messages for signalling GstNavigation changes.
       
    57  * </para>
       
    58  * </listitem>
       
    59  * </itemizedlist>
       
    60  */
       
    61 
       
    62 #ifdef HAVE_CONFIG_H
    22 #ifdef HAVE_CONFIG_H
    63 #include "config.h"
    23 #include "config.h"
    64 #endif
    24 #endif
    65 
    25 
    66 #include <gst/interfaces/navigation.h>
    26 #include <gst/interfaces/navigation.h>
    67 #include <gst/interfaces/interfaces-enumtypes.h>
       
    68 
    27 
    69 static void gst_navigation_class_init (GstNavigationInterface * iface);
    28 static void gst_navigation_class_init (GstNavigationInterface * iface);
    70 
       
    71 #define GST_NAVIGATION_MESSAGE_NAME "GstNavigationMessage"
       
    72 #define GST_NAVIGATION_QUERY_NAME "GstNavigationQuery"
       
    73 #define GST_NAVIGATION_EVENT_NAME "application/x-gst-navigation"
       
    74 
       
    75 #ifdef __SYMBIAN32__
    29 #ifdef __SYMBIAN32__
    76 EXPORT_C
    30 EXPORT_C
    77 #endif
    31 #endif
       
    32 
    78 
    33 
    79 GType
    34 GType
    80 gst_navigation_get_type (void)
    35 gst_navigation_get_type (void)
    81 {
    36 {
    82   static GType gst_navigation_type = 0;
    37   static GType gst_navigation_type = 0;
   121 
    76 
   122   if (iface->send_event) {
    77   if (iface->send_event) {
   123     iface->send_event (navigation, structure);
    78     iface->send_event (navigation, structure);
   124   }
    79   }
   125 }
    80 }
   126 
       
   127 /**
       
   128  * gst_navigation_send_mouse_event:
       
   129  * @navigation: The navigation interface instance
       
   130  * @event: The type of the key event. Recognised values are "key-press" and
       
   131  * "key-release"
       
   132  * @key: Character representation of the key. This is typically as produced
       
   133  * by XKeysymToString.
       
   134  */
       
   135 #ifdef __SYMBIAN32__
    81 #ifdef __SYMBIAN32__
   136 EXPORT_C
    82 EXPORT_C
   137 #endif
    83 #endif
       
    84 
   138 
    85 
   139 void
    86 void
   140 gst_navigation_send_key_event (GstNavigation * navigation, const char *event,
    87 gst_navigation_send_key_event (GstNavigation * navigation, const char *event,
   141     const char *key)
    88     const char *key)
   142 {
    89 {
   143   gst_navigation_send_event (navigation,
    90   gst_navigation_send_event (navigation,
   144       gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING,
    91       gst_structure_new ("application/x-gst-navigation", "event", G_TYPE_STRING,
   145           event, "key", G_TYPE_STRING, key, NULL));
    92           event, "key", G_TYPE_STRING, key, NULL));
   146 }
    93 }
   147 
       
   148 /**
       
   149  * gst_navigation_send_mouse_event:
       
   150  * @navigation: The navigation interface instance
       
   151  * @event: The type of mouse event, as a text string. Recognised values are
       
   152  * "mouse-button-press", "mouse-button-release" and "mouse-move".
       
   153  * @button: The button number of the button being pressed or released. Pass 0
       
   154  * for mouse-move events.
       
   155  * @x: The x coordinate of the mouse event.
       
   156  * @y: The y coordinate of the mouse event.
       
   157  *
       
   158  * Sends a mouse event to the navigation interface. Mouse event coordinates
       
   159  * are sent relative to the display space of the related output area. This is
       
   160  * usually the size in pixels of the window associated with the element
       
   161  * implementing the #GstNavigation interface.
       
   162  *
       
   163  */
       
   164 #ifdef __SYMBIAN32__
    94 #ifdef __SYMBIAN32__
   165 EXPORT_C
    95 EXPORT_C
   166 #endif
    96 #endif
       
    97 
   167 
    98 
   168 void
    99 void
   169 gst_navigation_send_mouse_event (GstNavigation * navigation, const char *event,
   100 gst_navigation_send_mouse_event (GstNavigation * navigation, const char *event,
   170     int button, double x, double y)
   101     int button, double x, double y)
   171 {
   102 {
   172   gst_navigation_send_event (navigation,
   103   gst_navigation_send_event (navigation,
   173       gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING,
   104       gst_structure_new ("application/x-gst-navigation", "event", G_TYPE_STRING,
   174           event, "button", G_TYPE_INT, button, "pointer_x", G_TYPE_DOUBLE, x,
   105           event, "button", G_TYPE_INT, button, "pointer_x", G_TYPE_DOUBLE, x,
   175           "pointer_y", G_TYPE_DOUBLE, y, NULL));
   106           "pointer_y", G_TYPE_DOUBLE, y, NULL));
   176 }
   107 }
   177 
       
   178 /**
       
   179  * gst_navigation_send_command:
       
   180  * @navigation: The navigation interface instance
       
   181  * @command: The command to issue
       
   182  *
       
   183  * Sends the indicated command to the navigation interface.
       
   184  *
       
   185  * Since: 0.10.23
       
   186  */
       
   187 #ifdef __SYMBIAN32__
       
   188 EXPORT_C
       
   189 #endif
       
   190 
       
   191 void
       
   192 gst_navigation_send_command (GstNavigation * navigation,
       
   193     GstNavigationCommand command)
       
   194 {
       
   195   gst_navigation_send_event (navigation,
       
   196       gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING,
       
   197           "command", "command-code", G_TYPE_UINT, (guint) command, NULL));
       
   198 }
       
   199 
       
   200 /* Navigation Queries */
       
   201 
       
   202 #define GST_NAVIGATION_QUERY_HAS_TYPE(query,query_type) \
       
   203 (gst_navigation_query_get_type (query) == GST_NAVIGATION_QUERY_ ## query_type)
       
   204 
       
   205 /**
       
   206  * gst_navigation_query_get_type:
       
   207  * @query: The query to inspect
       
   208  *
       
   209  * Inspect a #GstQuery and return the #GstNavigationQueryType associated with
       
   210  * it if it is a #GstNavigation query.
       
   211  *
       
   212  * Returns: The #GstNavigationQueryType of the query, or
       
   213  * #GST_NAVIGATION_QUERY_INVALID
       
   214  * Since: 0.10.23
       
   215  */
       
   216 #ifdef __SYMBIAN32__
       
   217 EXPORT_C
       
   218 #endif
       
   219 
       
   220 GstNavigationQueryType
       
   221 gst_navigation_query_get_type (GstQuery * query)
       
   222 {
       
   223   const GstStructure *s;
       
   224   const gchar *q_type;
       
   225 
       
   226   if (query == NULL || GST_QUERY_TYPE (query) != GST_QUERY_CUSTOM)
       
   227     return GST_NAVIGATION_QUERY_INVALID;
       
   228 
       
   229   s = gst_query_get_structure (query);
       
   230   if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_QUERY_NAME))
       
   231     return GST_NAVIGATION_QUERY_INVALID;
       
   232 
       
   233   q_type = gst_structure_get_string (s, "type");
       
   234   if (q_type == NULL)
       
   235     return GST_NAVIGATION_QUERY_INVALID;
       
   236 
       
   237   if (g_str_equal (q_type, "commands"))
       
   238     return GST_NAVIGATION_QUERY_COMMANDS;
       
   239   else if (g_str_equal (q_type, "angles"))
       
   240     return GST_NAVIGATION_QUERY_ANGLES;
       
   241 
       
   242   return GST_NAVIGATION_QUERY_INVALID;
       
   243 }
       
   244 
       
   245 /**
       
   246  * gst_navigation_query_new_commands:
       
   247  *
       
   248  * Create a new #GstNavigation commands query. When executed, it will
       
   249  * query the pipeline for the set of currently available commands.
       
   250  *
       
   251  * Returns: The new query.
       
   252  * Since: 0.10.23
       
   253  */
       
   254 #ifdef __SYMBIAN32__
       
   255 EXPORT_C
       
   256 #endif
       
   257 
       
   258 GstQuery *
       
   259 gst_navigation_query_new_commands (void)
       
   260 {
       
   261   GstQuery *query;
       
   262   GstStructure *structure;
       
   263 
       
   264   structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME,
       
   265       "type", G_TYPE_STRING, "commands", NULL);
       
   266   query = gst_query_new_application (GST_QUERY_CUSTOM, structure);
       
   267 
       
   268   return query;
       
   269 }
       
   270 
       
   271 static void
       
   272 gst_query_list_add_command (GValue * list, GstNavigationCommand val)
       
   273 {
       
   274   GValue item = { 0, };
       
   275 
       
   276   g_value_init (&item, GST_TYPE_NAVIGATION_COMMAND);
       
   277   g_value_set_enum (&item, val);
       
   278   gst_value_list_append_value (list, &item);
       
   279   g_value_unset (&item);
       
   280 }
       
   281 
       
   282 /**
       
   283  * gst_navigation_query_set_commands:
       
   284  * @query: a #GstQuery
       
   285  * @n_cmds: the number of commands to set.
       
   286  * @...: A list of @GstNavigationCommand values, @n_cmds entries long.
       
   287  *
       
   288  * Set the #GstNavigation command query result fields in @query. The number
       
   289  * of commands passed must be equal to @n_commands.
       
   290  *
       
   291  * Since: 0.10.23
       
   292  */
       
   293 #ifdef __SYMBIAN32__
       
   294 EXPORT_C
       
   295 #endif
       
   296 
       
   297 void
       
   298 gst_navigation_query_set_commands (GstQuery * query, gint n_cmds, ...)
       
   299 {
       
   300   va_list ap;
       
   301   GValue list = { 0, };
       
   302   GstStructure *structure;
       
   303   gint i;
       
   304 
       
   305   g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS));
       
   306 
       
   307   g_value_init (&list, GST_TYPE_LIST);
       
   308 
       
   309   va_start (ap, n_cmds);
       
   310   for (i = 0; i < n_cmds; i++) {
       
   311     GstNavigationCommand val = va_arg (ap, GstNavigationCommand);
       
   312     gst_query_list_add_command (&list, val);
       
   313   }
       
   314   va_end (ap);
       
   315 
       
   316   structure = gst_query_get_structure (query);
       
   317   gst_structure_set_value (structure, "commands", &list);
       
   318 
       
   319   g_value_unset (&list);
       
   320 }
       
   321 
       
   322 /**
       
   323  * gst_navigation_query_set_commandsv:
       
   324  * @query: a #GstQuery
       
   325  * @n_cmds: the number of commands to set.
       
   326  * @cmds: An array containing @n_cmds @GstNavigationCommand values.
       
   327  *
       
   328  * Set the #GstNavigation command query result fields in @query. The number
       
   329  * of commands passed must be equal to @n_commands.
       
   330  *
       
   331  * Since: 0.10.23
       
   332  */
       
   333 #ifdef __SYMBIAN32__
       
   334 EXPORT_C
       
   335 #endif
       
   336 
       
   337 void
       
   338 gst_navigation_query_set_commandsv (GstQuery * query, gint n_cmds,
       
   339     GstNavigationCommand * cmds)
       
   340 {
       
   341   GValue list = { 0, };
       
   342   GstStructure *structure;
       
   343   gint i;
       
   344 
       
   345   g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS));
       
   346 
       
   347   g_value_init (&list, GST_TYPE_LIST);
       
   348   for (i = 0; i < n_cmds; i++) {
       
   349     gst_query_list_add_command (&list, cmds[i]);
       
   350   }
       
   351   structure = gst_query_get_structure (query);
       
   352   gst_structure_set_value (structure, "commands", &list);
       
   353 
       
   354   g_value_unset (&list);
       
   355 }
       
   356 
       
   357 /**
       
   358  * gst_navigation_query_parse_commands_length:
       
   359  * @query: a #GstQuery
       
   360  * @n_cmds: the number of commands in this query.
       
   361  *
       
   362  * Parse the number of commands in the #GstNavigation commands @query.
       
   363  *
       
   364  * Returns: %TRUE if the query could be successfully parsed. %FALSE if not.
       
   365  * Since: 0.10.23
       
   366  */
       
   367 #ifdef __SYMBIAN32__
       
   368 EXPORT_C
       
   369 #endif
       
   370 
       
   371 gboolean
       
   372 gst_navigation_query_parse_commands_length (GstQuery * query, guint * n_cmds)
       
   373 {
       
   374   GstStructure *structure;
       
   375   const GValue *list;
       
   376 
       
   377   g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE);
       
   378 
       
   379   if (n_cmds == NULL)
       
   380     return TRUE;
       
   381 
       
   382   structure = gst_query_get_structure (query);
       
   383   list = gst_structure_get_value (structure, "commands");
       
   384   if (list == NULL)
       
   385     *n_cmds = 0;
       
   386   else
       
   387     *n_cmds = gst_value_list_get_size (list);
       
   388 
       
   389   return TRUE;
       
   390 }
       
   391 
       
   392 /**
       
   393  * gst_navigation_query_parse_commands_nth:
       
   394  * @query: a #GstQuery
       
   395  * @nth: the nth command to retrieve.
       
   396  * @cmd: a pointer to store the nth command into.
       
   397  *
       
   398  * Parse the #GstNavigation command query and retrieve the @nth command from
       
   399  * it into @cmd. If the list contains less elements than @nth, @cmd will be
       
   400  * set to #GST_NAVIGATION_COMMAND_INVALID.
       
   401  *
       
   402  * Returns: %TRUE if the query could be successfully parsed. %FALSE if not.
       
   403  * Since: 0.10.23
       
   404  */
       
   405 #ifdef __SYMBIAN32__
       
   406 EXPORT_C
       
   407 #endif
       
   408 
       
   409 gboolean
       
   410 gst_navigation_query_parse_commands_nth (GstQuery * query, guint nth,
       
   411     GstNavigationCommand * cmd)
       
   412 {
       
   413   GstStructure *structure;
       
   414   const GValue *list;
       
   415 
       
   416   g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE);
       
   417 
       
   418   if (cmd == NULL)
       
   419     return TRUE;
       
   420 
       
   421   structure = gst_query_get_structure (query);
       
   422   list = gst_structure_get_value (structure, "commands");
       
   423   if (list == NULL) {
       
   424     *cmd = GST_NAVIGATION_COMMAND_INVALID;
       
   425   } else {
       
   426     if (nth < gst_value_list_get_size (list)) {
       
   427       *cmd = (GstNavigationCommand)
       
   428           g_value_get_enum (gst_value_list_get_value (list, nth));
       
   429     } else
       
   430       *cmd = GST_NAVIGATION_COMMAND_INVALID;
       
   431   }
       
   432 
       
   433   return TRUE;
       
   434 }
       
   435 
       
   436 /**
       
   437  * gst_navigation_query_new_angles:
       
   438  *
       
   439  * Create a new #GstNavigation angles query. When executed, it will
       
   440  * query the pipeline for the set of currently available angles, which may be
       
   441  * greater than one in a multiangle video.
       
   442  *
       
   443  * Returns: The new query.
       
   444  * Since: 0.10.23
       
   445  */
       
   446 #ifdef __SYMBIAN32__
       
   447 EXPORT_C
       
   448 #endif
       
   449 
       
   450 GstQuery *
       
   451 gst_navigation_query_new_angles (void)
       
   452 {
       
   453   GstQuery *query;
       
   454   GstStructure *structure;
       
   455 
       
   456   structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME,
       
   457       "type", G_TYPE_STRING, "angles", NULL);
       
   458   query = gst_query_new_application (GST_QUERY_CUSTOM, structure);
       
   459 
       
   460   return query;
       
   461 }
       
   462 
       
   463 /**
       
   464  * gst_navigation_query_set_angles:
       
   465  * @query: a #GstQuery
       
   466  * @cur_angle: the current viewing angle to set.
       
   467  * @n_angles: the number of viewing angles to set.
       
   468  *
       
   469  * Set the #GstNavigation angles query result field in @query.
       
   470  *
       
   471  * Since: 0.10.23
       
   472  */
       
   473 #ifdef __SYMBIAN32__
       
   474 EXPORT_C
       
   475 #endif
       
   476 
       
   477 void
       
   478 gst_navigation_query_set_angles (GstQuery * query, guint cur_angle,
       
   479     guint n_angles)
       
   480 {
       
   481   GstStructure *structure;
       
   482 
       
   483   g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES));
       
   484 
       
   485   structure = gst_query_get_structure (query);
       
   486   gst_structure_set (structure,
       
   487       "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL);
       
   488 }
       
   489 
       
   490 /**
       
   491  * gst_navigation_query_parse_angles:
       
   492  * @query: a #GstQuery
       
   493  * @cur_angle: Pointer to a #guint into which to store the currently selected
       
   494  * angle value from the query, or NULL
       
   495  * @n_angles: Pointer to a #guint into which to store the number of angles
       
   496  * value from the query, or NULL
       
   497  *
       
   498  * Parse the current angle number in the #GstNavigation angles @query into the
       
   499  * #guint pointed to by the @cur_angle variable, and the number of available
       
   500  * angles into the #guint pointed to by the @n_angles variable.
       
   501  *
       
   502  * Returns: %TRUE if the query could be successfully parsed. %FALSE if not.
       
   503  * Since: 0.10.23
       
   504  */
       
   505 #ifdef __SYMBIAN32__
       
   506 EXPORT_C
       
   507 #endif
       
   508 
       
   509 gboolean
       
   510 gst_navigation_query_parse_angles (GstQuery * query, guint * cur_angle,
       
   511     guint * n_angles)
       
   512 {
       
   513   GstStructure *structure;
       
   514 
       
   515   g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES), FALSE);
       
   516 
       
   517   structure = gst_query_get_structure (query);
       
   518 
       
   519   if (cur_angle)
       
   520     g_return_val_if_fail (gst_structure_get_uint (structure,
       
   521             "angle", cur_angle), FALSE);
       
   522 
       
   523   if (n_angles)
       
   524     g_return_val_if_fail (gst_structure_get_uint (structure,
       
   525             "angles", n_angles), FALSE);
       
   526 
       
   527   return TRUE;
       
   528 }
       
   529 
       
   530 /* Navigation Messages */
       
   531 
       
   532 #define GST_NAVIGATION_MESSAGE_HAS_TYPE(msg,msg_type) \
       
   533 (gst_navigation_message_get_type (msg) == GST_NAVIGATION_MESSAGE_ ## msg_type)
       
   534 
       
   535 /**
       
   536  * gst_navigation_message_get_type:
       
   537  * @message: A #GstMessage to inspect.
       
   538  *
       
   539  * Check a bus message to see if it is a #GstNavigation event, and return
       
   540  * the #GstNavigationMessageType identifying the type of the message if so.
       
   541  *
       
   542  * Returns: The type of the #GstNavigationMessage, or
       
   543  * #GST_NAVIGATION_MESSAGE_INVALID if the message is not a #GstNavigation
       
   544  * notification.
       
   545  *
       
   546  * Since: 0.10.23
       
   547  */
       
   548 #ifdef __SYMBIAN32__
       
   549 EXPORT_C
       
   550 #endif
       
   551 
       
   552 GstNavigationMessageType
       
   553 gst_navigation_message_get_type (GstMessage * message)
       
   554 {
       
   555   const GstStructure *s;
       
   556   const gchar *m_type;
       
   557 
       
   558   if (message == NULL || GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
       
   559     return GST_NAVIGATION_MESSAGE_INVALID;
       
   560 
       
   561   s = gst_message_get_structure (message);
       
   562   if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_MESSAGE_NAME))
       
   563     return GST_NAVIGATION_MESSAGE_INVALID;
       
   564 
       
   565   m_type = gst_structure_get_string (s, "type");
       
   566   if (m_type == NULL)
       
   567     return GST_NAVIGATION_MESSAGE_INVALID;
       
   568 
       
   569   if (g_str_equal (m_type, "mouse-over"))
       
   570     return GST_NAVIGATION_MESSAGE_MOUSE_OVER;
       
   571   else if (g_str_equal (m_type, "commands-changed"))
       
   572     return GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED;
       
   573   else if (g_str_equal (m_type, "angles-changed"))
       
   574     return GST_NAVIGATION_MESSAGE_ANGLES_CHANGED;
       
   575 
       
   576   return GST_NAVIGATION_MESSAGE_INVALID;
       
   577 }
       
   578 
       
   579 /**
       
   580  * gst_navigation_message_new_mouse_over:
       
   581  * @src: A #GstObject to set as source of the new message.
       
   582  * @active: %TRUE if the mouse has entered a clickable area of the display.
       
   583  * %FALSE if it over a non-clickable area.
       
   584  *
       
   585  * Creates a new #GstNavigation message with type
       
   586  * #GST_NAVIGATION_MESSAGE_MOUSE_OVER.
       
   587  *
       
   588  * Returns: The new #GstMessage.
       
   589  * Since: 0.10.23
       
   590  */
       
   591 #ifdef __SYMBIAN32__
       
   592 EXPORT_C
       
   593 #endif
       
   594 
       
   595 GstMessage *
       
   596 gst_navigation_message_new_mouse_over (GstObject * src, gboolean active)
       
   597 {
       
   598   GstStructure *s;
       
   599   GstMessage *m;
       
   600 
       
   601   s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME,
       
   602       "type", G_TYPE_STRING, "mouse-over", "active", G_TYPE_BOOLEAN, active,
       
   603       NULL);
       
   604 
       
   605   m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s);
       
   606 
       
   607   return m;
       
   608 }
       
   609 
       
   610 /**
       
   611  * gst_navigation_message_parse_mouse_over:
       
   612  * @message: A #GstMessage to inspect.
       
   613  * @active: A pointer to a gboolean to receive the active/inactive state,
       
   614  * or NULL.
       
   615  *
       
   616  * Parse a #GstNavigation message of type #GST_NAVIGATION_MESSAGE_MOUSE_OVER
       
   617  * and extract the active/inactive flag. If the mouse over event is marked
       
   618  * active, it indicates that the mouse is over a clickable area.
       
   619  *
       
   620  * Returns: %TRUE if the message could be successfully parsed. %FALSE if not.
       
   621  * Since: 0.10.23
       
   622  */
       
   623 #ifdef __SYMBIAN32__
       
   624 EXPORT_C
       
   625 #endif
       
   626 
       
   627 gboolean
       
   628 gst_navigation_message_parse_mouse_over (GstMessage * message,
       
   629     gboolean * active)
       
   630 {
       
   631   if (!GST_NAVIGATION_MESSAGE_HAS_TYPE (message, MOUSE_OVER))
       
   632     return FALSE;
       
   633 
       
   634   if (active) {
       
   635     const GstStructure *s = gst_message_get_structure (message);
       
   636     if (gst_structure_get_boolean (s, "active", active) == FALSE)
       
   637       return FALSE;
       
   638   }
       
   639 
       
   640   return TRUE;
       
   641 }
       
   642 
       
   643 /**
       
   644  * gst_navigation_message_new_commands_changed:
       
   645  * @src: A #GstObject to set as source of the new message.
       
   646  *
       
   647  * Creates a new #GstNavigation message with type
       
   648  * #GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED
       
   649  *
       
   650  * Returns: The new #GstMessage.
       
   651  * Since: 0.10.23
       
   652  */
       
   653 #ifdef __SYMBIAN32__
       
   654 EXPORT_C
       
   655 #endif
       
   656 
       
   657 GstMessage *
       
   658 gst_navigation_message_new_commands_changed (GstObject * src)
       
   659 {
       
   660   GstStructure *s;
       
   661   GstMessage *m;
       
   662 
       
   663   s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME,
       
   664       "type", G_TYPE_STRING, "commands-changed", NULL);
       
   665 
       
   666   m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s);
       
   667 
       
   668   return m;
       
   669 }
       
   670 
       
   671 /**
       
   672  * gst_navigation_message_new_angles_changed:
       
   673  * @src: A #GstObject to set as source of the new message.
       
   674  * @cur_angle: The currently selected angle.
       
   675  * @n_angles: The number of viewing angles now available.
       
   676  *
       
   677  * Creates a new #GstNavigation message with type
       
   678  * #GST_NAVIGATION_MESSAGE_ANGLES_CHANGED for notifying an application
       
   679  * that the current angle, or current number of angles available in a
       
   680  * multiangle video has changed.
       
   681  *
       
   682  * Returns: The new #GstMessage.
       
   683  * Since: 0.10.23
       
   684  */
       
   685 #ifdef __SYMBIAN32__
       
   686 EXPORT_C
       
   687 #endif
       
   688 
       
   689 GstMessage *
       
   690 gst_navigation_message_new_angles_changed (GstObject * src, guint cur_angle,
       
   691     guint n_angles)
       
   692 {
       
   693   GstStructure *s;
       
   694   GstMessage *m;
       
   695 
       
   696   s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME,
       
   697       "type", G_TYPE_STRING, "angles-changed",
       
   698       "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL);
       
   699 
       
   700   m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s);
       
   701 
       
   702   return m;
       
   703 }
       
   704 
       
   705 /**
       
   706  * gst_navigation_message_parse_angles_changed:
       
   707  * @message: A #GstMessage to inspect.
       
   708  * @cur_angle: A pointer to a #guint to receive the new current angle number,
       
   709  * or NULL
       
   710  * @n_angles: A pointer to a #guint to receive the new angle count, or NULL.
       
   711  *
       
   712  * Parse a #GstNavigation message of type GST_NAVIGATION_MESSAGE_ANGLES_CHANGED
       
   713  * and extract the @cur_angle and @n_angles parameters.
       
   714  *
       
   715  * Returns: %TRUE if the message could be successfully parsed. %FALSE if not.
       
   716  * Since: 0.10.23
       
   717  */
       
   718 #ifdef __SYMBIAN32__
       
   719 EXPORT_C
       
   720 #endif
       
   721 
       
   722 gboolean
       
   723 gst_navigation_message_parse_angles_changed (GstMessage * message,
       
   724     guint * cur_angle, guint * n_angles)
       
   725 {
       
   726   const GstStructure *s;
       
   727 
       
   728   g_return_val_if_fail (GST_NAVIGATION_MESSAGE_HAS_TYPE (message,
       
   729           ANGLES_CHANGED), FALSE);
       
   730 
       
   731   s = gst_message_get_structure (message);
       
   732   if (cur_angle)
       
   733     g_return_val_if_fail (gst_structure_get_uint (s, "angle", cur_angle),
       
   734         FALSE);
       
   735 
       
   736   if (n_angles)
       
   737     g_return_val_if_fail (gst_structure_get_uint (s, "angles", n_angles),
       
   738         FALSE);
       
   739 
       
   740   return TRUE;
       
   741 }
       
   742 
       
   743 #define GST_NAVIGATION_EVENT_HAS_TYPE(event,event_type) \
       
   744 (gst_navigation_event_get_type (event) == GST_NAVIGATION_EVENT_ ## event_type)
       
   745 
       
   746 /**
       
   747  * gst_navigation_event_get_type:
       
   748  * @event: A #GstEvent to inspect.
       
   749  *
       
   750  * Inspect a #GstEvent and return the #GstNavigationEventType of the event, or
       
   751  * #GST_NAVIGATION_EVENT_INVALID if the event is not a #GstNavigation event.
       
   752  *
       
   753  * Since: 0.10.23
       
   754  */
       
   755 #ifdef __SYMBIAN32__
       
   756 EXPORT_C
       
   757 #endif
       
   758 
       
   759 GstNavigationEventType
       
   760 gst_navigation_event_get_type (GstEvent * event)
       
   761 {
       
   762   const GstStructure *s;
       
   763   const gchar *e_type;
       
   764 
       
   765   if (event == NULL || GST_EVENT_TYPE (event) != GST_EVENT_NAVIGATION)
       
   766     return GST_NAVIGATION_EVENT_INVALID;
       
   767 
       
   768   s = gst_event_get_structure (event);
       
   769   if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_EVENT_NAME))
       
   770     return GST_NAVIGATION_EVENT_INVALID;
       
   771 
       
   772   e_type = gst_structure_get_string (s, "event");
       
   773   if (e_type == NULL)
       
   774     return GST_NAVIGATION_EVENT_INVALID;
       
   775 
       
   776   if (g_str_equal (e_type, "mouse-button-press"))
       
   777     return GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS;
       
   778   else if (g_str_equal (e_type, "mouse-button-release"))
       
   779     return GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE;
       
   780   else if (g_str_equal (e_type, "mouse-move"))
       
   781     return GST_NAVIGATION_EVENT_MOUSE_MOVE;
       
   782   else if (g_str_equal (e_type, "key-press"))
       
   783     return GST_NAVIGATION_EVENT_KEY_PRESS;
       
   784   else if (g_str_equal (e_type, "key-release"))
       
   785     return GST_NAVIGATION_EVENT_KEY_RELEASE;
       
   786   else if (g_str_equal (e_type, "command"))
       
   787     return GST_NAVIGATION_EVENT_COMMAND;
       
   788 
       
   789   return GST_NAVIGATION_EVENT_INVALID;
       
   790 }
       
   791 
       
   792 /**
       
   793  * gst_navigation_event_parse_key_event:
       
   794  * @event: A #GstEvent to inspect.
       
   795  * @key: A pointer to a location to receive the string identifying the key
       
   796  * press. The returned string is owned by the event, and valid only until the
       
   797  * event is unreffed.
       
   798  *
       
   799  * Since: 0.10.23
       
   800  */
       
   801 #ifdef __SYMBIAN32__
       
   802 EXPORT_C
       
   803 #endif
       
   804 
       
   805 gboolean
       
   806 gst_navigation_event_parse_key_event (GstEvent * event, const gchar ** key)
       
   807 {
       
   808   GstNavigationEventType e_type;
       
   809   const GstStructure *s;
       
   810 
       
   811   e_type = gst_navigation_event_get_type (event);
       
   812   g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_KEY_PRESS ||
       
   813       e_type == GST_NAVIGATION_EVENT_KEY_RELEASE, FALSE);
       
   814 
       
   815   if (key) {
       
   816     s = gst_event_get_structure (event);
       
   817     *key = gst_structure_get_string (s, "key");
       
   818     if (*key == NULL)
       
   819       return FALSE;
       
   820   }
       
   821 
       
   822   return TRUE;
       
   823 }
       
   824 
       
   825 /**
       
   826  * gst_navigation_event_parse_mouse_button_event:
       
   827  * @event: A #GstEvent to inspect.
       
   828  * @button: Pointer to a gint that will receive the button number associated
       
   829  * with the event.
       
   830  * @x: Pointer to a gdouble to receive the x coordinate of the mouse button
       
   831  * event.
       
   832  * @y: Pointer to a gdouble to receive the y coordinate of the mouse button
       
   833  * event.
       
   834  * 
       
   835  * Retrieve the details of either a #GstNavigation mouse button press event or
       
   836  * a mouse button release event. Determine which type the event is using
       
   837  * gst_navigation_event_get_type() to retrieve the #GstNavigationEventType.
       
   838  *
       
   839  * Since: 0.10.23
       
   840  */
       
   841 #ifdef __SYMBIAN32__
       
   842 EXPORT_C
       
   843 #endif
       
   844 
       
   845 gboolean
       
   846 gst_navigation_event_parse_mouse_button_event (GstEvent * event, gint * button,
       
   847     gdouble * x, gdouble * y)
       
   848 {
       
   849   GstNavigationEventType e_type;
       
   850   const GstStructure *s;
       
   851 
       
   852   e_type = gst_navigation_event_get_type (event);
       
   853   g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS ||
       
   854       e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE, FALSE);
       
   855 
       
   856   s = gst_event_get_structure (event);
       
   857   if (x)
       
   858     g_return_val_if_fail (gst_structure_get_double (s, "pointer_x", x), FALSE);
       
   859   if (y)
       
   860     g_return_val_if_fail (gst_structure_get_double (s, "pointer_y", y), FALSE);
       
   861   if (button)
       
   862     g_return_val_if_fail (gst_structure_get_int (s, "button", button), FALSE);
       
   863 
       
   864   return TRUE;
       
   865 }
       
   866 
       
   867 /**
       
   868  * gst_navigation_event_parse_mouse_move_event:
       
   869  * @event: A #GstEvent to inspect.
       
   870  * @x: Pointer to a gdouble to receive the x coordinate of the mouse movement.
       
   871  * @y: Pointer to a gdouble to receive the y coordinate of the mouse movement.
       
   872  *
       
   873  * Inspect a #GstNavigation mouse movement event and extract the coordinates
       
   874  * of the event.
       
   875  *
       
   876  * Since: 0.10.23
       
   877  */
       
   878 #ifdef __SYMBIAN32__
       
   879 EXPORT_C
       
   880 #endif
       
   881 
       
   882 gboolean
       
   883 gst_navigation_event_parse_mouse_move_event (GstEvent * event, gdouble * x,
       
   884     gdouble * y)
       
   885 {
       
   886   const GstStructure *s;
       
   887 
       
   888   g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, MOUSE_MOVE),
       
   889       FALSE);
       
   890 
       
   891   s = gst_event_get_structure (event);
       
   892   if (x)
       
   893     g_return_val_if_fail (gst_structure_get_double (s, "pointer_x", x), FALSE);
       
   894   if (y)
       
   895     g_return_val_if_fail (gst_structure_get_double (s, "pointer_y", y), FALSE);
       
   896 
       
   897   return TRUE;
       
   898 }
       
   899 
       
   900 /**
       
   901  * gst_navigation_event_parse_command:
       
   902  * @event: A #GstEvent to inspect.
       
   903  * @command: Pointer to GstNavigationCommand to receive the type of the
       
   904  * navigation event.
       
   905  *
       
   906  * Inspect a #GstNavigation command event and retrieve the enum value of the
       
   907  * associated command.
       
   908  *
       
   909  * Since: 0.10.23
       
   910  */
       
   911 #ifdef __SYMBIAN32__
       
   912 EXPORT_C
       
   913 #endif
       
   914 
       
   915 gboolean
       
   916 gst_navigation_event_parse_command (GstEvent * event,
       
   917     GstNavigationCommand * command)
       
   918 {
       
   919   const GstStructure *s;
       
   920   g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, COMMAND), FALSE);
       
   921 
       
   922   if (command) {
       
   923     s = gst_event_get_structure (event);
       
   924     g_return_val_if_fail (gst_structure_get_uint (s, "command-code", (guint*)command),
       
   925         FALSE);
       
   926   }
       
   927 
       
   928   return TRUE;
       
   929 }