tests/check/: use the new macro
[platform/upstream/gstreamer.git] / gst / gstquery.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wim.taymans@chello.be>
4  *                    2005 Wim Taymans <wim@fluendo.com>
5  *
6  * gstquery.c: GstQueryType registration and Query parsing/creation
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /**
25  * SECTION:gstquery
26  * @short_description: Dynamically register new query types. Provide functions
27  *                     to create queries, and to set and parse values in them.
28  * @see_also: #GstPad, #GstElement
29  *
30  * GstQuery functions are used to register a new query types to the gstreamer
31  * core.
32  * Query types can be used to perform queries on pads and elements.
33  *
34  * Queries can be created using the gst_query_new_xxx() functions.  
35  * Query values can be set using gst_query_set_xxx(), and parsed using 
36  * gst_query_parse_xxx() helpers.
37  *
38  * The following example shows how to query the duration of a pipeline:
39  * 
40  * <example>
41  *  <title>Query duration on a pipeline</title>
42  *  <programlisting>
43  *  GstQuery *query;
44  *  gboolean res;
45  *  query = gst_query_new_duration (GST_FORMAT_TIME);
46  *  res = gst_element_query (pipeline, query);
47  *  if (res) {
48  *    gint64 duration;
49  *    gst_query_parse_duration (query, NULL, &amp;duration);
50  *    g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration));
51  *  }
52  *  else {
53  *    g_print ("duration query failed...");
54  *  }
55  *  gst_query_unref (query);
56  *  </programlisting>
57  * </example>
58  *
59  * Last reviewed on 2006-02-14 (0.10.4)
60  */
61
62 #include "gst_private.h"
63 #include <string.h>
64 #include "gstquery.h"
65 #include "gstvalue.h"
66 #include "gstenumtypes.h"
67
68 GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
69 #define GST_CAT_DEFAULT gst_query_debug
70
71 static void gst_query_init (GTypeInstance * instance, gpointer g_class);
72 static void gst_query_class_init (gpointer g_class, gpointer class_data);
73 static void gst_query_finalize (GstQuery * query);
74 static GstQuery *_gst_query_copy (GstQuery * query);
75
76
77 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
78 static GList *_gst_queries = NULL;
79 static GHashTable *_nick_to_query = NULL;
80 static GHashTable *_query_type_to_nick = NULL;
81 static guint32 _n_values = 1;   /* we start from 1 because 0 reserved for NONE */
82
83 static GstQueryTypeDefinition standard_definitions[] = {
84   {GST_QUERY_POSITION, "position", "Current position", 0},
85   {GST_QUERY_DURATION, "duration", "Total duration", 0},
86   {GST_QUERY_LATENCY, "latency", "Latency", 0},
87   {GST_QUERY_JITTER, "jitter", "Jitter", 0},
88   {GST_QUERY_RATE, "rate", "Configured rate 1000000 = 1", 0},
89   {GST_QUERY_SEEKING, "seeking", "Seeking capabilities and parameters", 0},
90   {GST_QUERY_SEGMENT, "segment", "currently configured segment", 0},
91   {GST_QUERY_CONVERT, "convert", "Converting between formats", 0},
92   {GST_QUERY_FORMATS, "formats", "Supported formats for conversion", 0},
93   {0, NULL, NULL, 0}
94 };
95
96 void
97 _gst_query_initialize (void)
98 {
99   GstQueryTypeDefinition *standards = standard_definitions;
100
101   GST_CAT_INFO (GST_CAT_GST_INIT, "init queries");
102
103   GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system");
104
105   g_static_mutex_lock (&mutex);
106   if (_nick_to_query == NULL) {
107     _nick_to_query = g_hash_table_new (g_str_hash, g_str_equal);
108     _query_type_to_nick = g_hash_table_new (NULL, NULL);
109   }
110
111   while (standards->nick) {
112     standards->quark = g_quark_from_static_string (standards->nick);
113     g_hash_table_insert (_nick_to_query, standards->nick, standards);
114     g_hash_table_insert (_query_type_to_nick,
115         GINT_TO_POINTER (standards->value), standards);
116
117     _gst_queries = g_list_append (_gst_queries, standards);
118     standards++;
119     _n_values++;
120   }
121   g_static_mutex_unlock (&mutex);
122
123   gst_query_get_type ();
124 }
125
126 /**
127  * gst_query_type_get_name:
128  * @query: the query type
129  *
130  * Get a printable name for the given query type. Do not modify or free.
131  *
132  * Returns: a reference to the static name of the query.
133  */
134 const gchar *
135 gst_query_type_get_name (GstQueryType query)
136 {
137   const GstQueryTypeDefinition *def;
138
139   def = gst_query_type_get_details (query);
140
141   return def->nick;
142 }
143
144 /**
145  * gst_query_type_to_quark:
146  * @query: the query type
147  *
148  * Get the unique quark for the given query type.
149  *
150  * Returns: the quark associated with the query type
151  */
152 GQuark
153 gst_query_type_to_quark (GstQueryType query)
154 {
155   const GstQueryTypeDefinition *def;
156
157   def = gst_query_type_get_details (query);
158
159   return def->quark;
160 }
161
162 GType
163 gst_query_get_type (void)
164 {
165   static GType _gst_query_type;
166
167   if (G_UNLIKELY (_gst_query_type == 0)) {
168     static const GTypeInfo query_info = {
169       sizeof (GstQueryClass),
170       NULL,
171       NULL,
172       gst_query_class_init,
173       NULL,
174       NULL,
175       sizeof (GstQuery),
176       0,
177       gst_query_init,
178       NULL
179     };
180
181     _gst_query_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
182         "GstQuery", &query_info, 0);
183   }
184   return _gst_query_type;
185 }
186
187 static void
188 gst_query_class_init (gpointer g_class, gpointer class_data)
189 {
190   GstQueryClass *query_class = GST_QUERY_CLASS (g_class);
191
192   query_class->mini_object_class.copy =
193       (GstMiniObjectCopyFunction) _gst_query_copy;
194   query_class->mini_object_class.finalize =
195       (GstMiniObjectFinalizeFunction) gst_query_finalize;
196
197 }
198
199 static void
200 gst_query_finalize (GstQuery * query)
201 {
202   g_return_if_fail (query != NULL);
203
204   if (query->structure) {
205     gst_structure_set_parent_refcount (query->structure, NULL);
206     gst_structure_free (query->structure);
207   }
208 }
209
210 static void
211 gst_query_init (GTypeInstance * instance, gpointer g_class)
212 {
213
214 }
215
216 static GstQuery *
217 _gst_query_copy (GstQuery * query)
218 {
219   GstQuery *copy;
220
221   copy = (GstQuery *) gst_mini_object_new (GST_TYPE_QUERY);
222
223   copy->type = query->type;
224
225   if (query->structure) {
226     copy->structure = gst_structure_copy (query->structure);
227     gst_structure_set_parent_refcount (copy->structure,
228         &query->mini_object.refcount);
229   }
230
231   return copy;
232 }
233
234
235
236 /**
237  * gst_query_type_register:
238  * @nick: The nick of the new query
239  * @description: The description of the new query
240  *
241  * Create a new GstQueryType based on the nick or return an
242  * already registered query with that nick
243  *
244  * Returns: A new GstQueryType or an already registered query
245  * with the same nick.
246  */
247 GstQueryType
248 gst_query_type_register (const gchar * nick, const gchar * description)
249 {
250   GstQueryTypeDefinition *query;
251   GstQueryType lookup;
252
253   g_return_val_if_fail (nick != NULL, 0);
254   g_return_val_if_fail (description != NULL, 0);
255
256   lookup = gst_query_type_get_by_nick (nick);
257   if (lookup != GST_QUERY_NONE)
258     return lookup;
259
260   query = g_new0 (GstQueryTypeDefinition, 1);
261   query->value = _n_values;
262   query->nick = g_strdup (nick);
263   query->description = g_strdup (description);
264   query->quark = g_quark_from_static_string (query->nick);
265
266   g_static_mutex_lock (&mutex);
267   g_hash_table_insert (_nick_to_query, query->nick, query);
268   g_hash_table_insert (_query_type_to_nick, GINT_TO_POINTER (query->value),
269       query);
270   _gst_queries = g_list_append (_gst_queries, query);
271   _n_values++;
272   g_static_mutex_unlock (&mutex);
273
274   return query->value;
275 }
276
277 /**
278  * gst_query_type_get_by_nick:
279  * @nick: The nick of the query
280  *
281  * Get the query type registered with @nick.
282  *
283  * Returns: The query registered with @nick or #GST_QUERY_NONE
284  * if the query was not registered.
285  */
286 GstQueryType
287 gst_query_type_get_by_nick (const gchar * nick)
288 {
289   GstQueryTypeDefinition *query;
290
291   g_return_val_if_fail (nick != NULL, 0);
292
293   g_static_mutex_lock (&mutex);
294   query = g_hash_table_lookup (_nick_to_query, nick);
295   g_static_mutex_unlock (&mutex);
296
297   if (query != NULL)
298     return query->value;
299   else
300     return GST_QUERY_NONE;
301 }
302
303 /**
304  * gst_query_types_contains:
305  * @types: The query array to search
306  * @type: the #GstQueryType to find
307  *
308  * See if the given #GstQueryType is inside the @types query types array.
309  *
310  * Returns: TRUE if the type is found inside the array
311  */
312 gboolean
313 gst_query_types_contains (const GstQueryType * types, GstQueryType type)
314 {
315   if (!types)
316     return FALSE;
317
318   while (*types) {
319     if (*types == type)
320       return TRUE;
321
322     types++;
323   }
324   return FALSE;
325 }
326
327
328 /**
329  * gst_query_type_get_details:
330  * @type: a #GstQueryType
331  *
332  * Get details about the given #GstQueryType.
333  *
334  * Returns: The #GstQueryTypeDefinition for @type or NULL on failure.
335  */
336 const GstQueryTypeDefinition *
337 gst_query_type_get_details (GstQueryType type)
338 {
339   const GstQueryTypeDefinition *result;
340
341   g_static_mutex_lock (&mutex);
342   result = g_hash_table_lookup (_query_type_to_nick, GINT_TO_POINTER (type));
343   g_static_mutex_unlock (&mutex);
344
345   return result;
346 }
347
348 /**
349  * gst_query_type_iterate_definitions:
350  *
351  * Get a #GstIterator of all the registered query types. The definitions 
352  * iterated over are read only.
353  *
354  * Returns: A #GstIterator of #GstQueryTypeDefinition.
355  */
356 GstIterator *
357 gst_query_type_iterate_definitions (void)
358 {
359   GstIterator *result;
360
361   g_static_mutex_lock (&mutex);
362   /* FIXME: register a boxed type for GstQueryTypeDefinition */
363   result = gst_iterator_new_list (G_TYPE_POINTER,
364       g_static_mutex_get_mutex (&mutex), &_n_values, &_gst_queries,
365       NULL, NULL, NULL);
366   g_static_mutex_unlock (&mutex);
367
368   return result;
369 }
370
371 static GstQuery *
372 gst_query_new (GstQueryType type, GstStructure * structure)
373 {
374   GstQuery *query;
375
376   query = (GstQuery *) gst_mini_object_new (GST_TYPE_QUERY);
377
378   GST_DEBUG ("creating new query %p %d", query, type);
379
380   query->type = type;
381
382   if (structure) {
383     query->structure = structure;
384     gst_structure_set_parent_refcount (query->structure,
385         &query->mini_object.refcount);
386   } else {
387     query->structure = NULL;
388   }
389
390   return query;
391 }
392
393 /**
394  * gst_query_new_position:
395  * @format: the default #GstFormat for the new query
396  *
397  * Constructs a new query stream position query object. Use gst_query_unref()
398  * when done with it. A position query is used to query the current position
399  * of playback in the streams, in some format.
400  *
401  * Returns: A #GstQuery
402  */
403 GstQuery *
404 gst_query_new_position (GstFormat format)
405 {
406   GstQuery *query;
407   GstStructure *structure;
408
409   structure = gst_structure_new ("GstQueryPosition",
410       "format", GST_TYPE_FORMAT, format,
411       "cur", G_TYPE_INT64, (gint64) - 1, NULL);
412   query = gst_query_new (GST_QUERY_POSITION, structure);
413
414   return query;
415 }
416
417 /**
418  * gst_query_set_position:
419  * @query: a #GstQuery with query type GST_QUERY_POSITION
420  * @format: the requested #GstFormat
421  * @cur: the position to set
422  *
423  * Answer a position query by setting the requested value in the given format.
424  */
425 void
426 gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur)
427 {
428   GstStructure *structure;
429
430   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
431
432   structure = gst_query_get_structure (query);
433   gst_structure_set (structure,
434       "format", GST_TYPE_FORMAT, format, "cur", G_TYPE_INT64, cur, NULL);
435 }
436
437 /**
438  * gst_query_parse_position:
439  * @query: a #GstQuery
440  * @format: the storage for the #GstFormat of the position values (may be NULL)
441  * @cur: the storage for the current position (may be NULL)
442  *
443  * Parse a position query, writing the format into @format, and the position
444  * into @cur, if the respective parameters are non-NULL.
445  */
446 void
447 gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
448 {
449   GstStructure *structure;
450
451   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
452
453   structure = gst_query_get_structure (query);
454   if (format)
455     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
456   if (cur)
457     *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
458 }
459
460
461 /**
462  * gst_query_new_duration:
463  * @format: the #GstFormat for this duration query
464  *
465  * Constructs a new stream duration query object to query in the given format. 
466  * Use gst_query_unref() when done with it. A duration query will give the
467  * total length of the stream.
468  *
469  * Returns: A #GstQuery
470  */
471 GstQuery *
472 gst_query_new_duration (GstFormat format)
473 {
474   GstQuery *query;
475   GstStructure *structure;
476
477   structure = gst_structure_new ("GstQueryDuration",
478       "format", GST_TYPE_FORMAT, format,
479       "duration", G_TYPE_INT64, (gint64) - 1, NULL);
480   query = gst_query_new (GST_QUERY_DURATION, structure);
481
482   return query;
483 }
484
485 /**
486  * gst_query_set_duration:
487  * @query: a #GstQuery
488  * @format: the #GstFormat for the duration
489  * @duration: the duration of the stream
490  *
491  * Answer a duration query by setting the requested value in the given format.
492  */
493 void
494 gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration)
495 {
496   GstStructure *structure;
497
498   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
499
500   structure = gst_query_get_structure (query);
501   gst_structure_set (structure,
502       "format", GST_TYPE_FORMAT, format,
503       "duration", G_TYPE_INT64, duration, NULL);
504 }
505
506 /**
507  * gst_query_parse_duration:
508  * @query: a #GstQuery
509  * @format: the storage for the #GstFormat of the duration value, or NULL.
510  * @duration: the storage for the total duration, or NULL.
511  *
512  * Parse a duration query answer. Write the format of the duration into @format,
513  * and the value into @duration, if the respective variables are non-NULL.
514  */
515 void
516 gst_query_parse_duration (GstQuery * query, GstFormat * format,
517     gint64 * duration)
518 {
519   GstStructure *structure;
520
521   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
522
523   structure = gst_query_get_structure (query);
524   if (format)
525     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
526   if (duration)
527     *duration =
528         g_value_get_int64 (gst_structure_get_value (structure, "duration"));
529 }
530
531 /**
532  * gst_query_new_convert:
533  * @src_format: the source #GstFormat for the new query
534  * @value: the value to convert
535  * @dest_format: the target #GstFormat
536  *
537  * Constructs a new convert query object. Use gst_query_unref()
538  * when done with it. A convert query is used to ask for a conversion between
539  * one format and another.
540  *
541  * Returns: A #GstQuery
542  */
543 GstQuery *
544 gst_query_new_convert (GstFormat src_format, gint64 value,
545     GstFormat dest_format)
546 {
547   GstQuery *query;
548   GstStructure *structure;
549
550   g_return_val_if_fail (value >= 0, NULL);
551
552   structure = gst_structure_new ("GstQueryConvert",
553       "src_format", GST_TYPE_FORMAT, src_format,
554       "src_value", G_TYPE_INT64, value,
555       "dest_format", GST_TYPE_FORMAT, dest_format,
556       "dest_value", G_TYPE_INT64, (gint64) - 1, NULL);
557   query = gst_query_new (GST_QUERY_CONVERT, structure);
558
559   return query;
560 }
561
562 /**
563  * gst_query_set_convert:
564  * @query: a #GstQuery
565  * @src_format: the source #GstFormat
566  * @src_value: the source value
567  * @dest_format: the destination #GstFormat
568  * @dest_value: the destination value
569  *
570  * Answer a convert query by setting the requested values.
571  */
572 void
573 gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value,
574     GstFormat dest_format, gint64 dest_value)
575 {
576   GstStructure *structure;
577
578   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
579
580   structure = gst_query_get_structure (query);
581   gst_structure_set (structure,
582       "src_format", GST_TYPE_FORMAT, src_format,
583       "src_value", G_TYPE_INT64, src_value,
584       "dest_format", GST_TYPE_FORMAT, dest_format,
585       "dest_value", G_TYPE_INT64, dest_value, NULL);
586 }
587
588 /**
589  * gst_query_parse_convert:
590  * @query: a #GstQuery
591  * @src_format: the storage for the #GstFormat of the source value, or NULL
592  * @src_value: the storage for the source value, or NULL
593  * @dest_format: the storage for the #GstFormat of the destination value, or NULL
594  * @dest_value: the storage for the destination value, or NULL
595  *
596  * Parse a convert query answer. Any of @src_format, @src_value, @dest_format,
597  * and @dest_value may be NULL, in which case that value is omitted.
598  */
599 void
600 gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
601     gint64 * src_value, GstFormat * dest_format, gint64 * dest_value)
602 {
603   GstStructure *structure;
604
605   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
606
607   structure = gst_query_get_structure (query);
608   if (src_format)
609     *src_format =
610         g_value_get_enum (gst_structure_get_value (structure, "src_format"));
611   if (src_value)
612     *src_value =
613         g_value_get_int64 (gst_structure_get_value (structure, "src_value"));
614   if (dest_format)
615     *dest_format =
616         g_value_get_enum (gst_structure_get_value (structure, "dest_format"));
617   if (dest_value)
618     *dest_value =
619         g_value_get_int64 (gst_structure_get_value (structure, "dest_value"));
620 }
621
622 /**
623  * gst_query_new_segment:
624  * @format: the #GstFormat for the new query
625  *
626  * Constructs a new segment query object. Use gst_query_unref()
627  * when done with it. A segment query is used to discover information about the
628  * currently configured segment for playback.
629  *
630  * Returns: a #GstQuery
631  */
632 GstQuery *
633 gst_query_new_segment (GstFormat format)
634 {
635   GstQuery *query;
636   GstStructure *structure;
637
638   structure = gst_structure_new ("GstQuerySegment",
639       "format", GST_TYPE_FORMAT, format, NULL);
640   query = gst_query_new (GST_QUERY_SEGMENT, structure);
641
642   return query;
643 }
644
645 /**
646  * gst_query_set_segment:
647  * @query: a #GstQuery
648  * @rate: the rate of the segment
649  * @format: the #GstFormat of the segment values (@start_value and @stop_value)
650  * @start_value: the start value
651  * @stop_value: the stop value
652  *
653  * Answer a segment query by setting the requested values. The normal
654  * playback segment of a pipeline is 0 to duration at the default rate of
655  * 1.0. If a seek was performed on the pipeline to play a different
656  * segment, this query will return the range specified in the last seek.
657  *
658  * @start_value and @stop_value will respectively contain the configured 
659  * playback range start and stop values expressed in @format. 
660  * The values are always between 0 and the duration of the media and 
661  * @start_value <= @stop_value. @rate will contain the playback rate. For
662  * negative rates, playback will actually happen from @stop_value to
663  * @start_value.
664  */
665 void
666 gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format,
667     gint64 start_value, gint64 stop_value)
668 {
669   GstStructure *structure;
670
671   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
672
673   structure = gst_query_get_structure (query);
674   gst_structure_set (structure,
675       "rate", G_TYPE_DOUBLE, rate,
676       "format", GST_TYPE_FORMAT, format,
677       "start_value", G_TYPE_INT64, start_value,
678       "stop_value", G_TYPE_INT64, stop_value, NULL);
679 }
680
681 /**
682  * gst_query_parse_segment:
683  * @query: a #GstQuery
684  * @rate: the storage for the rate of the segment, or NULL
685  * @format: the storage for the #GstFormat of the values, or NULL
686  * @start_value: the storage for the start value, or NULL
687  * @stop_value: the storage for the stop value, or NULL
688  *
689  * Parse a segment query answer. Any of @rate, @format, @start_value, and 
690  * @stop_value may be NULL, which will cause this value to be omitted.
691  *
692  * See gst_query_set_segment() for an explanation of the function arguments.
693  */
694 void
695 gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
696     gint64 * start_value, gint64 * stop_value)
697 {
698   GstStructure *structure;
699
700   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
701
702   structure = gst_query_get_structure (query);
703   if (rate)
704     *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
705   if (format)
706     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
707   if (start_value)
708     *start_value =
709         g_value_get_int64 (gst_structure_get_value (structure, "start_value"));
710   if (stop_value)
711     *stop_value =
712         g_value_get_int64 (gst_structure_get_value (structure, "stop_value"));
713 }
714
715 /**
716  * gst_query_new_application:
717  * @type: the query type
718  * @structure: a structure for the query
719  *
720  * Constructs a new custom application query object. Use gst_query_unref()
721  * when done with it.
722  *
723  * Returns: a #GstQuery
724  */
725 GstQuery *
726 gst_query_new_application (GstQueryType type, GstStructure * structure)
727 {
728   g_return_val_if_fail (gst_query_type_get_details (type) != NULL, NULL);
729   g_return_val_if_fail (structure != NULL, NULL);
730
731   return gst_query_new (type, structure);
732 }
733
734 /**
735  * gst_query_get_structure:
736  * @query: a #GstQuery
737  *
738  * Get the structure of a query.
739  *
740  * Returns: The #GstStructure of the query. The structure is still owned
741  * by the query and will therefore be freed when the query is unreffed.
742  */
743 GstStructure *
744 gst_query_get_structure (GstQuery * query)
745 {
746   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
747
748   return query->structure;
749 }
750
751 /**
752  * gst_query_new_seeking (GstFormat *format)
753  * @format: the default #GstFormat for the new query
754  *
755  * Constructs a new query object for querying seeking properties of
756  * the stream. 
757  *
758  * Returns: A #GstQuery
759  */
760 GstQuery *
761 gst_query_new_seeking (GstFormat format)
762 {
763   GstQuery *query;
764   GstStructure *structure;
765
766   structure = gst_structure_new ("GstQuerySeeking",
767       "format", GST_TYPE_FORMAT, format,
768       "seekable", G_TYPE_BOOLEAN, FALSE,
769       "segment-start", G_TYPE_INT64, (gint64) - 1,
770       "segment-end", G_TYPE_INT64, (gint64) - 1, NULL);
771   query = gst_query_new (GST_QUERY_SEEKING, structure);
772
773   return query;
774 }
775
776 /**
777  * gst_query_set_seeking:
778  * @query: a #GstQuery
779  * @format: the format to set for the @segment_start and @segment_end values
780  * @seekable: the seekable flag to set
781  * @segment_start: the segment_start to set
782  * @segment_end: the segment_end to set
783  *
784  * Set the seeking query result fields in @query.
785  */
786 void
787 gst_query_set_seeking (GstQuery * query, GstFormat format,
788     gboolean seekable, gint64 segment_start, gint64 segment_end)
789 {
790   GstStructure *structure;
791
792   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
793
794   structure = gst_query_get_structure (query);
795   gst_structure_set (structure,
796       "format", GST_TYPE_FORMAT, format,
797       "seekable", G_TYPE_BOOLEAN, seekable,
798       "segment-start", G_TYPE_INT64, segment_start,
799       "segment-end", G_TYPE_INT64, segment_end, NULL);
800 }
801
802 /**
803  * gst_query_parse_seeking:
804  * @query: a GST_QUERY_SEEKING type query #GstQuery
805  * @format: the format to set for the @segment_start and @segment_end values
806  * @seekable: the seekable flag to set
807  * @segment_start: the segment_start to set
808  * @segment_end: the segment_end to set
809  *
810  * Parse a seeking query, writing the format into @format, and 
811  * other results into the passed parameters, if the respective parameters
812  * are non-NULL
813  */
814 void
815 gst_query_parse_seeking (GstQuery * query, GstFormat * format,
816     gboolean * seekable, gint64 * segment_start, gint64 * segment_end)
817 {
818   GstStructure *structure;
819
820   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
821
822   structure = gst_query_get_structure (query);
823   if (format)
824     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
825   if (seekable)
826     *seekable =
827         g_value_get_boolean (gst_structure_get_value (structure, "seekable"));
828   if (segment_start)
829     *segment_start =
830         g_value_get_int64 (gst_structure_get_value (structure,
831             "segment-start"));
832   if (segment_end)
833     *segment_end =
834         g_value_get_int64 (gst_structure_get_value (structure, "segment-end"));
835 }
836
837 /**
838  * gst_query_new_formats:
839  *
840  * Constructs a new query object for querying formats of
841  * the stream. 
842  *
843  * Returns: A #GstQuery
844  *
845  * Since: 0.10.4
846  */
847 GstQuery *
848 gst_query_new_formats (void)
849 {
850   GstQuery *query;
851   GstStructure *structure;
852
853   structure = gst_structure_new ("GstQueryFormats", NULL);
854   query = gst_query_new (GST_QUERY_FORMATS, structure);
855
856   return query;
857 }
858
859 static void
860 gst_query_list_add_format (GValue * list, GstFormat format)
861 {
862   GValue item = { 0, };
863
864   g_value_init (&item, GST_TYPE_FORMAT);
865   g_value_set_enum (&item, format);
866   gst_value_list_append_value (list, &item);
867   g_value_unset (&item);
868 }
869
870 /**
871  * gst_query_set_formats:
872  * @query: a #GstQuery
873  * @n_formats: the number of formats to set.
874  * @...: A number of @GstFormats equal to @n_formats.
875  *
876  * Set the formats query result fields in @query. The number of formats passed
877  * must be equal to @n_formats.
878  */
879 void
880 gst_query_set_formats (GstQuery * query, gint n_formats, ...)
881 {
882   va_list ap;
883   GValue list = { 0, };
884   GstStructure *structure;
885   gint i;
886
887   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
888
889   g_value_init (&list, GST_TYPE_LIST);
890
891   va_start (ap, n_formats);
892   for (i = 0; i < n_formats; i++) {
893     gst_query_list_add_format (&list, va_arg (ap, GstFormat));
894   }
895   va_end (ap);
896
897   structure = gst_query_get_structure (query);
898   gst_structure_set_value (structure, "formats", &list);
899
900   g_value_unset (&list);
901
902 }
903
904 /**
905  * gst_query_set_formatsv:
906  * @query: a #GstQuery
907  * @n_formats: the number of formats to set.
908  * @formats: An array containing @n_formats @GstFormat values.
909  *
910  * Set the formats query result fields in @query. The number of formats passed
911  * in the @formats array must be equal to @n_formats.
912  *
913  * Since: 0.10.4
914  */
915 void
916 gst_query_set_formatsv (GstQuery * query, gint n_formats, GstFormat * formats)
917 {
918   GValue list = { 0, };
919   GstStructure *structure;
920   gint i;
921
922   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
923
924   g_value_init (&list, GST_TYPE_LIST);
925   for (i = 0; i < n_formats; i++) {
926     gst_query_list_add_format (&list, formats[i]);
927   }
928   structure = gst_query_get_structure (query);
929   gst_structure_set_value (structure, "formats", &list);
930
931   g_value_unset (&list);
932 }
933
934 /**
935  * gst_query_parse_formats_length:
936  * @query: a #GstQuery
937  * @n_formats: the number of formats in this query.
938  *
939  * Parse the number of formats in the formats @query. 
940  *
941  * Since: 0.10.4
942  */
943 void
944 gst_query_parse_formats_length (GstQuery * query, guint * n_formats)
945 {
946   GstStructure *structure;
947
948   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
949
950   if (n_formats) {
951     const GValue *list;
952
953     structure = gst_query_get_structure (query);
954     list = gst_structure_get_value (structure, "formats");
955     if (list == NULL)
956       *n_formats = 0;
957     else
958       *n_formats = gst_value_list_get_size (list);
959   }
960 }
961
962 /**
963  * gst_query_parse_formats_nth:
964  * @query: a #GstQuery
965  * @nth: the nth format to retrieve.
966  * @format: a pointer to store the nth format
967  *
968  * Parse the format query and retrieve the @nth format from it into 
969  * @format. If the list contains less elements than @nth, @format will be
970  * set to GST_FORMAT_UNDEFINED.
971  *
972  * Since: 0.10.4
973  */
974 void
975 gst_query_parse_formats_nth (GstQuery * query, guint nth, GstFormat * format)
976 {
977   GstStructure *structure;
978
979   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
980
981   if (format) {
982     const GValue *list;
983
984     structure = gst_query_get_structure (query);
985     list = gst_structure_get_value (structure, "formats");
986     if (list == NULL) {
987       *format = GST_FORMAT_UNDEFINED;
988     } else {
989       if (nth < gst_value_list_get_size (list)) {
990         *format = g_value_get_enum (gst_value_list_get_value (list, nth));
991       } else
992         *format = GST_FORMAT_UNDEFINED;
993     }
994   }
995 }