Blame gst-libs/gst/video/navigation.c

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