query: register queries like events

Also register queries with a QueryType that allows us to check if the event is
sent in the right direction. Add a serialized query type because we will need
this for the allocation query.
Remove the QueryTypeDefinition stuff, it is not used anymore and we now use
custom queries and separate API for them.
Update defs.
This commit is contained in:
Wim Taymans 2012-03-14 14:51:16 +01:00
parent d8578d5c09
commit 5a21eb36c7
4 changed files with 147 additions and 244 deletions

View file

@ -704,6 +704,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
g_type_class_ref (gst_plugin_flags_get_type ()); g_type_class_ref (gst_plugin_flags_get_type ());
g_type_class_ref (gst_plugin_dependency_flags_get_type ()); g_type_class_ref (gst_plugin_dependency_flags_get_type ());
g_type_class_ref (gst_rank_get_type ()); g_type_class_ref (gst_rank_get_type ());
g_type_class_ref (gst_query_type_flags_get_type ());
g_type_class_ref (gst_query_type_get_type ()); g_type_class_ref (gst_query_type_get_type ());
g_type_class_ref (gst_buffering_mode_get_type ()); g_type_class_ref (gst_buffering_mode_get_type ());
g_type_class_ref (gst_stream_status_type_get_type ()); g_type_class_ref (gst_stream_status_type_get_type ());
@ -1069,6 +1070,7 @@ gst_deinit (void)
g_type_class_unref (g_type_class_peek (gst_plugin_error_get_type ())); g_type_class_unref (g_type_class_peek (gst_plugin_error_get_type ()));
g_type_class_unref (g_type_class_peek (gst_plugin_flags_get_type ())); g_type_class_unref (g_type_class_peek (gst_plugin_flags_get_type ()));
g_type_class_unref (g_type_class_peek (gst_rank_get_type ())); g_type_class_unref (g_type_class_peek (gst_rank_get_type ()));
g_type_class_unref (g_type_class_peek (gst_query_type_flags_get_type ()));
g_type_class_unref (g_type_class_peek (gst_query_type_get_type ())); g_type_class_unref (g_type_class_peek (gst_query_type_get_type ()));
g_type_class_unref (g_type_class_peek (gst_buffering_mode_get_type ())); g_type_class_unref (g_type_class_peek (gst_buffering_mode_get_type ()));
g_type_class_unref (g_type_class_peek (gst_tag_merge_mode_get_type ())); g_type_class_unref (g_type_class_peek (gst_tag_merge_mode_get_type ()));

View file

@ -96,30 +96,33 @@ typedef struct
gint64 stop; gint64 stop;
} GstQueryBufferingRange; } GstQueryBufferingRange;
static GMutex mutex; typedef struct
static GList *_gst_queries = NULL; {
static GHashTable *_nick_to_query = NULL; const gint type;
static GHashTable *_query_type_to_nick = NULL; const gchar *name;
static guint32 _n_values = 1; /* we start from 1 because 0 reserved for NONE */ GQuark quark;
} GstQueryQuarks;
static GstQueryTypeDefinition standard_definitions[] = { static GstQueryQuarks query_quarks[] = {
{GST_QUERY_POSITION, "position", "Current position", 0}, {GST_QUERY_UNKNOWN, "unknown", 0},
{GST_QUERY_DURATION, "duration", "Total duration", 0}, {GST_QUERY_POSITION, "position", 0},
{GST_QUERY_LATENCY, "latency", "Latency", 0}, {GST_QUERY_DURATION, "duration", 0},
{GST_QUERY_JITTER, "jitter", "Jitter", 0}, {GST_QUERY_LATENCY, "latency", 0},
{GST_QUERY_RATE, "rate", "Configured rate 1000000 = 1", 0}, {GST_QUERY_JITTER, "jitter", 0},
{GST_QUERY_SEEKING, "seeking", "Seeking capabilities and parameters", 0}, {GST_QUERY_RATE, "rate", 0},
{GST_QUERY_SEGMENT, "segment", "currently configured segment", 0}, {GST_QUERY_SEEKING, "seeking", 0},
{GST_QUERY_CONVERT, "convert", "Converting between formats", 0}, {GST_QUERY_SEGMENT, "segment", 0},
{GST_QUERY_FORMATS, "formats", "Supported formats for conversion", 0}, {GST_QUERY_CONVERT, "convert", 0},
{GST_QUERY_BUFFERING, "buffering", "Buffering status", 0}, {GST_QUERY_FORMATS, "formats", 0},
{GST_QUERY_CUSTOM, "custom", "Custom query", 0}, {GST_QUERY_BUFFERING, "buffering", 0},
{GST_QUERY_URI, "uri", "URI of the source or sink", 0}, {GST_QUERY_CUSTOM, "custom", 0},
{GST_QUERY_ALLOCATION, "allocation", "Allocation properties", 0}, {GST_QUERY_URI, "uri", 0},
{GST_QUERY_SCHEDULING, "scheduling", "Scheduling properties", 0}, {GST_QUERY_ALLOCATION, "allocation", 0},
{GST_QUERY_ACCEPT_CAPS, "accept-caps", "Accept caps", 0}, {GST_QUERY_SCHEDULING, "scheduling", 0},
{GST_QUERY_CAPS, "caps", "Caps", 0}, {GST_QUERY_ACCEPT_CAPS, "accept-caps", 0},
{GST_QUERY_NONE, NULL, NULL, 0} {GST_QUERY_CAPS, "caps", 0},
{0, NULL, 0}
}; };
GST_DEFINE_MINI_OBJECT_TYPE (GstQuery, gst_query); GST_DEFINE_MINI_OBJECT_TYPE (GstQuery, gst_query);
@ -127,205 +130,73 @@ GST_DEFINE_MINI_OBJECT_TYPE (GstQuery, gst_query);
void void
_priv_gst_query_initialize (void) _priv_gst_query_initialize (void)
{ {
GstQueryTypeDefinition *standards = standard_definitions; gint i;
GST_CAT_INFO (GST_CAT_GST_INIT, "init queries"); _gst_query_type = gst_query_get_type ();
GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system"); GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system");
g_mutex_lock (&mutex); for (i = 0; query_quarks[i].name; i++) {
if (_nick_to_query == NULL) { query_quarks[i].quark = g_quark_from_static_string (query_quarks[i].name);
_nick_to_query = g_hash_table_new (g_str_hash, g_str_equal);
_query_type_to_nick = g_hash_table_new (NULL, NULL);
} }
while (standards->nick) {
standards->quark = g_quark_from_static_string (standards->nick);
g_hash_table_insert (_nick_to_query, (gpointer) standards->nick, standards);
g_hash_table_insert (_query_type_to_nick,
GINT_TO_POINTER (standards->value), standards);
_gst_queries = g_list_append (_gst_queries, standards);
standards++;
_n_values++;
}
g_mutex_unlock (&mutex);
_gst_query_type = gst_query_get_type ();
} }
/** /**
* gst_query_type_get_name: * gst_query_type_get_name:
* @query: the query type * @type: the query type
* *
* Get a printable name for the given query type. Do not modify or free. * Get a printable name for the given query type. Do not modify or free.
* *
* Returns: a reference to the static name of the query. * Returns: a reference to the static name of the query.
*/ */
const gchar * const gchar *
gst_query_type_get_name (GstQueryType query) gst_query_type_get_name (GstQueryType type)
{ {
const GstQueryTypeDefinition *def; gint i;
def = gst_query_type_get_details (query); for (i = 0; query_quarks[i].name; i++) {
g_return_val_if_fail (def != NULL, NULL); if (type == query_quarks[i].type)
return query_quarks[i].name;
return def->nick; }
return "unknown";
} }
/** /**
* gst_query_type_to_quark: * gst_query_type_to_quark:
* @query: the query type * @type: the query type
* *
* Get the unique quark for the given query type. * Get the unique quark for the given query type.
* *
* Returns: the quark associated with the query type * Returns: the quark associated with the query type
*/ */
GQuark GQuark
gst_query_type_to_quark (GstQueryType query) gst_query_type_to_quark (GstQueryType type)
{ {
const GstQueryTypeDefinition *def; gint i;
def = gst_query_type_get_details (query); for (i = 0; query_quarks[i].name; i++) {
g_return_val_if_fail (def != NULL, 0); if (type == query_quarks[i].type)
return query_quarks[i].quark;
return def->quark;
}
/**
* gst_query_type_register:
* @nick: The nick of the new query
* @description: The description of the new query
*
* Create a new GstQueryType based on the nick or return an
* already registered query with that nick
*
* Returns: A new GstQueryType or an already registered query
* with the same nick.
*/
GstQueryType
gst_query_type_register (const gchar * nick, const gchar * description)
{
GstQueryTypeDefinition *query;
GstQueryType lookup;
g_return_val_if_fail (nick != NULL, GST_QUERY_NONE);
g_return_val_if_fail (description != NULL, GST_QUERY_NONE);
lookup = gst_query_type_get_by_nick (nick);
if (lookup != GST_QUERY_NONE)
return lookup;
query = g_slice_new (GstQueryTypeDefinition);
query->value = (GstQueryType) _n_values;
query->nick = g_strdup (nick);
query->description = g_strdup (description);
query->quark = g_quark_from_static_string (query->nick);
g_mutex_lock (&mutex);
g_hash_table_insert (_nick_to_query, (gpointer) query->nick, query);
g_hash_table_insert (_query_type_to_nick, GINT_TO_POINTER (query->value),
query);
_gst_queries = g_list_append (_gst_queries, query);
_n_values++;
g_mutex_unlock (&mutex);
return query->value;
}
/**
* gst_query_type_get_by_nick:
* @nick: The nick of the query
*
* Get the query type registered with @nick.
*
* Returns: The query registered with @nick or #GST_QUERY_NONE
* if the query was not registered.
*/
GstQueryType
gst_query_type_get_by_nick (const gchar * nick)
{
GstQueryTypeDefinition *query;
g_return_val_if_fail (nick != NULL, GST_QUERY_NONE);
g_mutex_lock (&mutex);
query = g_hash_table_lookup (_nick_to_query, nick);
g_mutex_unlock (&mutex);
if (query != NULL)
return query->value;
else
return GST_QUERY_NONE;
}
/**
* gst_query_types_contains:
* @types: The query array to search
* @type: the #GstQueryType to find
*
* See if the given #GstQueryType is inside the @types query types array.
*
* Returns: TRUE if the type is found inside the array
*/
gboolean
gst_query_types_contains (const GstQueryType * types, GstQueryType type)
{
if (!types)
return FALSE;
while (*types) {
if (*types == type)
return TRUE;
types++;
} }
return FALSE; return 0;
} }
/** /**
* gst_query_type_get_details: * gst_query_type_get_flags:
* @type: a #GstQueryType * @type: a #GstQueryType
* *
* Get details about the given #GstQueryType. * Gets the #GstQueryTypeFlags associated with @type.
* *
* Returns: The #GstQueryTypeDefinition for @type or NULL on failure. * Returns: a #GstQueryTypeFlags.
*/ */
const GstQueryTypeDefinition * GstQueryTypeFlags
gst_query_type_get_details (GstQueryType type) gst_query_type_get_flags (GstQueryType type)
{ {
const GstQueryTypeDefinition *result; GstQueryTypeFlags ret;
g_mutex_lock (&mutex); ret = type & ((1 << GST_EVENT_NUM_SHIFT) - 1);
result = g_hash_table_lookup (_query_type_to_nick, GINT_TO_POINTER (type));
g_mutex_unlock (&mutex);
return result; return ret;
}
/**
* gst_query_type_iterate_definitions:
*
* Get a #GstIterator of all the registered query types. The definitions
* iterated over are read only.
*
* Free-function: gst_iterator_free
*
* Returns: (transfer full): a #GstIterator of #GstQueryTypeDefinition.
*/
GstIterator *
gst_query_type_iterate_definitions (void)
{
GstIterator *result;
g_mutex_lock (&mutex);
/* FIXME: register a boxed type for GstQueryTypeDefinition */
result = gst_iterator_new_list (G_TYPE_POINTER,
&mutex, &_n_values, &_gst_queries, NULL, NULL);
g_mutex_unlock (&mutex);
return result;
} }
static void static void

View file

@ -36,9 +36,53 @@
G_BEGIN_DECLS G_BEGIN_DECLS
typedef struct _GstQuery GstQuery;
/**
* GstQueryTypeFlags:
* @GST_QUERY_TYPE_UPSTREAM: Set if the query can travel upstream.
* @GST_QUERY_TYPE_DOWNSTREAM: Set if the query can travel downstream.
* @GST_QUERY_TYPE_SERIALIZED: Set if the query should be serialized with data
* flow.
*
* #GstQueryTypeFlags indicate the aspects of the different #GstQueryType
* values. You can get the type flags of a #GstQueryType with the
* gst_query_type_get_flags() function.
*/
typedef enum {
GST_QUERY_TYPE_UPSTREAM = 1 << 0,
GST_QUERY_TYPE_DOWNSTREAM = 1 << 1,
GST_QUERY_TYPE_SERIALIZED = 1 << 2
} GstQueryTypeFlags;
/**
* GST_QUERY_TYPE_BOTH:
*
* The same thing as #GST_QUERY_TYPE_UPSTREAM | #GST_QUERY_TYPE_DOWNSTREAM.
*/
#define GST_QUERY_TYPE_BOTH \
(GST_QUERY_TYPE_UPSTREAM | GST_QUERY_TYPE_DOWNSTREAM)
#define GST_QUERY_NUM_SHIFT (8)
/**
* GST_QUERY_MAKE_TYPE:
* @num: the query number to create
* @idx: the index in the sticky array
* @flags: the query flags
*
* when making custom query types, use this macro with the num and
* the given flags
*/
#define GST_QUERY_MAKE_TYPE(num,flags) \
(((num) << GST_QUERY_NUM_SHIFT) | (flags))
#define FLAG(name) GST_QUERY_TYPE_##name
/** /**
* GstQueryType: * GstQueryType:
* @GST_QUERY_NONE: invalid query type * @GST_QUERY_UNKNOWN: unknown query type
* @GST_QUERY_POSITION: current position in stream * @GST_QUERY_POSITION: current position in stream
* @GST_QUERY_DURATION: total duration of the stream * @GST_QUERY_DURATION: total duration of the stream
* @GST_QUERY_LATENCY: latency of stream * @GST_QUERY_LATENCY: latency of stream
@ -63,51 +107,31 @@ G_BEGIN_DECLS
/* NOTE: don't forget to update the table in gstquery.c when changing /* NOTE: don't forget to update the table in gstquery.c when changing
* this enum */ * this enum */
typedef enum { typedef enum {
GST_QUERY_NONE = 0, GST_QUERY_UNKNOWN = GST_QUERY_MAKE_TYPE (0, 0),
GST_QUERY_POSITION, GST_QUERY_POSITION = GST_QUERY_MAKE_TYPE (10, FLAG(BOTH)),
GST_QUERY_DURATION, GST_QUERY_DURATION = GST_QUERY_MAKE_TYPE (20, FLAG(BOTH)),
GST_QUERY_LATENCY, GST_QUERY_LATENCY = GST_QUERY_MAKE_TYPE (30, FLAG(BOTH)),
GST_QUERY_JITTER, /* not in draft-query, necessary? */ GST_QUERY_JITTER = GST_QUERY_MAKE_TYPE (40, FLAG(BOTH)),
GST_QUERY_RATE, GST_QUERY_RATE = GST_QUERY_MAKE_TYPE (50, FLAG(BOTH)),
GST_QUERY_SEEKING, GST_QUERY_SEEKING = GST_QUERY_MAKE_TYPE (60, FLAG(BOTH)),
GST_QUERY_SEGMENT, GST_QUERY_SEGMENT = GST_QUERY_MAKE_TYPE (70, FLAG(BOTH)),
GST_QUERY_CONVERT, GST_QUERY_CONVERT = GST_QUERY_MAKE_TYPE (80, FLAG(BOTH)),
GST_QUERY_FORMATS, GST_QUERY_FORMATS = GST_QUERY_MAKE_TYPE (90, FLAG(BOTH)),
GST_QUERY_BUFFERING, GST_QUERY_BUFFERING = GST_QUERY_MAKE_TYPE (110, FLAG(BOTH)),
GST_QUERY_CUSTOM, GST_QUERY_CUSTOM = GST_QUERY_MAKE_TYPE (120, FLAG(BOTH)),
GST_QUERY_URI, GST_QUERY_URI = GST_QUERY_MAKE_TYPE (130, FLAG(BOTH)),
GST_QUERY_ALLOCATION, GST_QUERY_ALLOCATION = GST_QUERY_MAKE_TYPE (140, FLAG(DOWNSTREAM) | FLAG(SERIALIZED)),
GST_QUERY_SCHEDULING, GST_QUERY_SCHEDULING = GST_QUERY_MAKE_TYPE (150, FLAG(UPSTREAM)),
GST_QUERY_ACCEPT_CAPS, GST_QUERY_ACCEPT_CAPS = GST_QUERY_MAKE_TYPE (160, FLAG(BOTH)),
GST_QUERY_CAPS GST_QUERY_CAPS = GST_QUERY_MAKE_TYPE (170, FLAG(BOTH))
} GstQueryType; } GstQueryType;
#undef FLAG
typedef struct _GstQueryTypeDefinition GstQueryTypeDefinition;
typedef struct _GstQuery GstQuery;
/**
* GstQueryTypeDefinition:
* @value: the unique id of the Query type
* @nick: a short nick
* @description: a longer description of the query type
* @quark: the quark for the nick
*
* A Query Type definition
*/
struct _GstQueryTypeDefinition
{
GstQueryType value;
const gchar *nick;
const gchar *description;
GQuark quark;
};
#define GST_TYPE_QUERY (gst_query_get_type()) #define GST_TYPE_QUERY (gst_query_get_type())
#define GST_IS_QUERY(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_QUERY)) #define GST_IS_QUERY(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_QUERY))
#define GST_QUERY_CAST(obj) ((GstQuery*)(obj)) #define GST_QUERY_CAST(obj) ((GstQuery*)(obj))
#define GST_QUERY(obj) (GST_QUERY_CAST(obj)) #define GST_QUERY(obj) (GST_QUERY_CAST(obj))
/** /**
* GST_QUERY_TYPE: * GST_QUERY_TYPE:
* @query: the query to query * @query: the query to query
@ -126,6 +150,28 @@ struct _GstQueryTypeDefinition
*/ */
#define GST_QUERY_TYPE_NAME(query) (gst_query_type_get_name(GST_QUERY_TYPE(query))) #define GST_QUERY_TYPE_NAME(query) (gst_query_type_get_name(GST_QUERY_TYPE(query)))
/**
* GST_QUERY_IS_UPSTREAM:
* @ev: the query to query
*
* Check if an query can travel upstream.
*/
#define GST_QUERY_IS_UPSTREAM(ev) !!(GST_QUERY_TYPE (ev) & GST_QUERY_TYPE_UPSTREAM)
/**
* GST_QUERY_IS_DOWNSTREAM:
* @ev: the query to query
*
* Check if an query can travel downstream.
*/
#define GST_QUERY_IS_DOWNSTREAM(ev) !!(GST_QUERY_TYPE (ev) & GST_QUERY_TYPE_DOWNSTREAM)
/**
* GST_QUERY_IS_SERIALIZED:
* @ev: the query to query
*
* Check if an query is serialized with the data stream.
*/
#define GST_QUERY_IS_SERIALIZED(ev) !!(GST_QUERY_TYPE (ev) & GST_QUERY_TYPE_SERIALIZED)
/** /**
* GstQuery: * GstQuery:
@ -142,26 +188,14 @@ struct _GstQuery
GstQueryType type; GstQueryType type;
}; };
const gchar* gst_query_type_get_name (GstQueryType query); const gchar* gst_query_type_get_name (GstQueryType type);
GQuark gst_query_type_to_quark (GstQueryType query); GQuark gst_query_type_to_quark (GstQueryType type);
GstQueryTypeFlags
gst_query_type_get_flags (GstQueryType type);
GType gst_query_get_type (void); GType gst_query_get_type (void);
/* register a new query */
GstQueryType gst_query_type_register (const gchar *nick,
const gchar *description);
GstQueryType gst_query_type_get_by_nick (const gchar *nick);
/* check if a query is in an array of querys */
gboolean gst_query_types_contains (const GstQueryType *types,
GstQueryType type);
/* query for query details */
const GstQueryTypeDefinition*
gst_query_type_get_details (GstQueryType type);
GstIterator* gst_query_type_iterate_definitions (void) G_GNUC_MALLOC;
/* refcounting */ /* refcounting */
/** /**
* gst_query_ref: * gst_query_ref:

View file

@ -206,7 +206,6 @@ EXPORTS
gst_caps_subtract gst_caps_subtract
gst_caps_to_string gst_caps_to_string
gst_caps_truncate gst_caps_truncate
gst_caps_union
gst_child_proxy_child_added gst_child_proxy_child_added
gst_child_proxy_child_removed gst_child_proxy_child_removed
gst_child_proxy_get gst_child_proxy_get
@ -874,14 +873,11 @@ EXPORTS
gst_query_set_seeking gst_query_set_seeking
gst_query_set_segment gst_query_set_segment
gst_query_set_uri gst_query_set_uri
gst_query_type_get_by_nick gst_query_type_flags_get_type
gst_query_type_get_details gst_query_type_get_flags
gst_query_type_get_name gst_query_type_get_name
gst_query_type_get_type gst_query_type_get_type
gst_query_type_iterate_definitions
gst_query_type_register
gst_query_type_to_quark gst_query_type_to_quark
gst_query_types_contains
gst_query_writable_structure gst_query_writable_structure
gst_rank_get_type gst_rank_get_type
gst_registry_add_feature gst_registry_add_feature