scheduling: port to new scheduling query
[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 new query types to the gstreamer
31  * core and use them.
32  * Queries can be performed on pads (gst_pad_query()) and elements
33  * (gst_element_query()). Please note that some queries might need a running
34  * pipeline to work.
35  *
36  * Queries can be created using the gst_query_new_*() functions.
37  * Query values can be set using gst_query_set_*(), and parsed using
38  * gst_query_parse_*() helpers.
39  *
40  * The following example shows how to query the duration of a pipeline:
41  *
42  * <example>
43  *  <title>Query duration on a pipeline</title>
44  *  <programlisting>
45  *  GstQuery *query;
46  *  gboolean res;
47  *  query = gst_query_new_duration (GST_FORMAT_TIME);
48  *  res = gst_element_query (pipeline, query);
49  *  if (res) {
50  *    gint64 duration;
51  *    gst_query_parse_duration (query, NULL, &amp;duration);
52  *    g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration));
53  *  }
54  *  else {
55  *    g_print ("duration query failed...");
56  *  }
57  *  gst_query_unref (query);
58  *  </programlisting>
59  * </example>
60  *
61  * Last reviewed on 2006-02-14 (0.10.4)
62  */
63
64 #include "gst_private.h"
65 #include "gstinfo.h"
66 #include "gstquery.h"
67 #include "gstvalue.h"
68 #include "gstenumtypes.h"
69 #include "gstquark.h"
70 #include "gsturi.h"
71 #include "gstbufferpool.h"
72
73 GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
74 #define GST_CAT_DEFAULT gst_query_debug
75
76 static GType _gst_query_type = 0;
77
78 typedef struct
79 {
80   GstQuery query;
81
82   GstStructure *structure;
83 } GstQueryImpl;
84
85 #define GST_QUERY_STRUCTURE(q)  (((GstQueryImpl *)(q))->structure)
86
87 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
88 static GList *_gst_queries = NULL;
89 static GHashTable *_nick_to_query = NULL;
90 static GHashTable *_query_type_to_nick = NULL;
91 static guint32 _n_values = 1;   /* we start from 1 because 0 reserved for NONE */
92
93 static GstQueryTypeDefinition standard_definitions[] = {
94   {GST_QUERY_POSITION, "position", "Current position", 0},
95   {GST_QUERY_DURATION, "duration", "Total duration", 0},
96   {GST_QUERY_LATENCY, "latency", "Latency", 0},
97   {GST_QUERY_JITTER, "jitter", "Jitter", 0},
98   {GST_QUERY_RATE, "rate", "Configured rate 1000000 = 1", 0},
99   {GST_QUERY_SEEKING, "seeking", "Seeking capabilities and parameters", 0},
100   {GST_QUERY_SEGMENT, "segment", "currently configured segment", 0},
101   {GST_QUERY_CONVERT, "convert", "Converting between formats", 0},
102   {GST_QUERY_FORMATS, "formats", "Supported formats for conversion", 0},
103   {GST_QUERY_BUFFERING, "buffering", "Buffering status", 0},
104   {GST_QUERY_CUSTOM, "custom", "Custom query", 0},
105   {GST_QUERY_URI, "uri", "URI of the source or sink", 0},
106   {GST_QUERY_ALLOCATION, "allocation", "Allocation properties", 0},
107   {GST_QUERY_SCHEDULING, "scheduling", "Scheduling properties", 0},
108   {0, NULL, NULL, 0}
109 };
110
111 void
112 _gst_query_initialize (void)
113 {
114   GstQueryTypeDefinition *standards = standard_definitions;
115
116   GST_CAT_INFO (GST_CAT_GST_INIT, "init queries");
117
118   GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system");
119
120   g_static_mutex_lock (&mutex);
121   if (_nick_to_query == NULL) {
122     _nick_to_query = g_hash_table_new (g_str_hash, g_str_equal);
123     _query_type_to_nick = g_hash_table_new (NULL, NULL);
124   }
125
126   while (standards->nick) {
127     standards->quark = g_quark_from_static_string (standards->nick);
128     g_hash_table_insert (_nick_to_query, (gpointer) standards->nick, standards);
129     g_hash_table_insert (_query_type_to_nick,
130         GINT_TO_POINTER (standards->value), standards);
131
132     _gst_queries = g_list_append (_gst_queries, standards);
133     standards++;
134     _n_values++;
135   }
136   g_static_mutex_unlock (&mutex);
137
138   gst_query_get_type ();
139 }
140
141 /**
142  * gst_query_type_get_name:
143  * @query: the query type
144  *
145  * Get a printable name for the given query type. Do not modify or free.
146  *
147  * Returns: a reference to the static name of the query.
148  */
149 const gchar *
150 gst_query_type_get_name (GstQueryType query)
151 {
152   const GstQueryTypeDefinition *def;
153
154   def = gst_query_type_get_details (query);
155   g_return_val_if_fail (def != NULL, NULL);
156
157   return def->nick;
158 }
159
160 /**
161  * gst_query_type_to_quark:
162  * @query: the query type
163  *
164  * Get the unique quark for the given query type.
165  *
166  * Returns: the quark associated with the query type
167  */
168 GQuark
169 gst_query_type_to_quark (GstQueryType query)
170 {
171   const GstQueryTypeDefinition *def;
172
173   def = gst_query_type_get_details (query);
174   g_return_val_if_fail (def != NULL, 0);
175
176   return def->quark;
177 }
178
179 GType
180 gst_query_get_type (void)
181 {
182   if (G_UNLIKELY (_gst_query_type == 0)) {
183     _gst_query_type = gst_mini_object_register ("GstQuery");
184   }
185   return _gst_query_type;
186 }
187
188
189 /**
190  * gst_query_type_register:
191  * @nick: The nick of the new query
192  * @description: The description of the new query
193  *
194  * Create a new GstQueryType based on the nick or return an
195  * already registered query with that nick
196  *
197  * Returns: A new GstQueryType or an already registered query
198  * with the same nick.
199  */
200 GstQueryType
201 gst_query_type_register (const gchar * nick, const gchar * description)
202 {
203   GstQueryTypeDefinition *query;
204   GstQueryType lookup;
205
206   g_return_val_if_fail (nick != NULL, GST_QUERY_NONE);
207   g_return_val_if_fail (description != NULL, GST_QUERY_NONE);
208
209   lookup = gst_query_type_get_by_nick (nick);
210   if (lookup != GST_QUERY_NONE)
211     return lookup;
212
213   query = g_slice_new (GstQueryTypeDefinition);
214   query->value = _n_values;
215   query->nick = g_strdup (nick);
216   query->description = g_strdup (description);
217   query->quark = g_quark_from_static_string (query->nick);
218
219   g_static_mutex_lock (&mutex);
220   g_hash_table_insert (_nick_to_query, (gpointer) query->nick, query);
221   g_hash_table_insert (_query_type_to_nick, GINT_TO_POINTER (query->value),
222       query);
223   _gst_queries = g_list_append (_gst_queries, query);
224   _n_values++;
225   g_static_mutex_unlock (&mutex);
226
227   return query->value;
228 }
229
230 /**
231  * gst_query_type_get_by_nick:
232  * @nick: The nick of the query
233  *
234  * Get the query type registered with @nick.
235  *
236  * Returns: The query registered with @nick or #GST_QUERY_NONE
237  * if the query was not registered.
238  */
239 GstQueryType
240 gst_query_type_get_by_nick (const gchar * nick)
241 {
242   GstQueryTypeDefinition *query;
243
244   g_return_val_if_fail (nick != NULL, GST_QUERY_NONE);
245
246   g_static_mutex_lock (&mutex);
247   query = g_hash_table_lookup (_nick_to_query, nick);
248   g_static_mutex_unlock (&mutex);
249
250   if (query != NULL)
251     return query->value;
252   else
253     return GST_QUERY_NONE;
254 }
255
256 /**
257  * gst_query_types_contains:
258  * @types: The query array to search
259  * @type: the #GstQueryType to find
260  *
261  * See if the given #GstQueryType is inside the @types query types array.
262  *
263  * Returns: TRUE if the type is found inside the array
264  */
265 gboolean
266 gst_query_types_contains (const GstQueryType * types, GstQueryType type)
267 {
268   if (!types)
269     return FALSE;
270
271   while (*types) {
272     if (*types == type)
273       return TRUE;
274
275     types++;
276   }
277   return FALSE;
278 }
279
280
281 /**
282  * gst_query_type_get_details:
283  * @type: a #GstQueryType
284  *
285  * Get details about the given #GstQueryType.
286  *
287  * Returns: The #GstQueryTypeDefinition for @type or NULL on failure.
288  */
289 const GstQueryTypeDefinition *
290 gst_query_type_get_details (GstQueryType type)
291 {
292   const GstQueryTypeDefinition *result;
293
294   g_static_mutex_lock (&mutex);
295   result = g_hash_table_lookup (_query_type_to_nick, GINT_TO_POINTER (type));
296   g_static_mutex_unlock (&mutex);
297
298   return result;
299 }
300
301 /**
302  * gst_query_type_iterate_definitions:
303  *
304  * Get a #GstIterator of all the registered query types. The definitions
305  * iterated over are read only.
306  *
307  * Free-function: gst_iterator_free
308  *
309  * Returns: (transfer full): a #GstIterator of #GstQueryTypeDefinition.
310  */
311 GstIterator *
312 gst_query_type_iterate_definitions (void)
313 {
314   GstIterator *result;
315
316   g_static_mutex_lock (&mutex);
317   /* FIXME: register a boxed type for GstQueryTypeDefinition */
318   result = gst_iterator_new_list (G_TYPE_POINTER,
319       g_static_mutex_get_mutex (&mutex), &_n_values, &_gst_queries, NULL, NULL);
320   g_static_mutex_unlock (&mutex);
321
322   return result;
323 }
324
325 static void
326 _gst_query_free (GstQuery * query)
327 {
328   GstStructure *s;
329
330   g_return_if_fail (query != NULL);
331
332   s = GST_QUERY_STRUCTURE (query);
333   if (s) {
334     gst_structure_set_parent_refcount (s, NULL);
335     gst_structure_free (s);
336   }
337
338   g_slice_free1 (GST_MINI_OBJECT_SIZE (query), query);
339 }
340
341 static GstQuery *gst_query_new (GstQueryType type, GstStructure * structure);
342
343 static GstQuery *
344 _gst_query_copy (GstQuery * query)
345 {
346   GstQuery *copy;
347
348   copy = gst_query_new (query->type, GST_QUERY_STRUCTURE (query));
349
350   return copy;
351 }
352
353 static GstQuery *
354 gst_query_new (GstQueryType type, GstStructure * structure)
355 {
356   GstQueryImpl *query;
357
358   query = g_slice_new0 (GstQueryImpl);
359
360   gst_mini_object_init (GST_MINI_OBJECT_CAST (query),
361       _gst_query_type, sizeof (GstQueryImpl));
362
363   query->query.mini_object.copy = (GstMiniObjectCopyFunction) _gst_query_copy;
364   query->query.mini_object.free = (GstMiniObjectFreeFunction) _gst_query_free;
365
366   GST_DEBUG ("creating new query %p %d", query, type);
367
368   GST_QUERY_TYPE (query) = type;
369   query->structure = structure;
370
371   if (structure)
372     gst_structure_set_parent_refcount (structure,
373         &query->query.mini_object.refcount);
374
375   return GST_QUERY_CAST (query);
376 }
377
378 /**
379  * gst_query_new_position:
380  * @format: the default #GstFormat for the new query
381  *
382  * Constructs a new query stream position query object. Use gst_query_unref()
383  * when done with it. A position query is used to query the current position
384  * of playback in the streams, in some format.
385  *
386  * Free-function: gst_query_unref
387  *
388  * Returns: (transfer full): a new #GstQuery
389  */
390 GstQuery *
391 gst_query_new_position (GstFormat format)
392 {
393   GstQuery *query;
394   GstStructure *structure;
395
396   structure = gst_structure_id_new (GST_QUARK (QUERY_POSITION),
397       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
398       GST_QUARK (CURRENT), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
399
400   query = gst_query_new (GST_QUERY_POSITION, structure);
401
402   return query;
403 }
404
405 /**
406  * gst_query_set_position:
407  * @query: a #GstQuery with query type GST_QUERY_POSITION
408  * @format: the requested #GstFormat
409  * @cur: the position to set
410  *
411  * Answer a position query by setting the requested value in the given format.
412  */
413 void
414 gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur)
415 {
416   GstStructure *structure;
417
418   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
419
420   structure = GST_QUERY_STRUCTURE (query);
421   gst_structure_id_set (structure,
422       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
423       GST_QUARK (CURRENT), G_TYPE_INT64, cur, NULL);
424 }
425
426 /**
427  * gst_query_parse_position:
428  * @query: a #GstQuery
429  * @format: (out) (allow-none): the storage for the #GstFormat of the
430  *     position values (may be NULL)
431  * @cur: (out) (allow-none): the storage for the current position (may be NULL)
432  *
433  * Parse a position query, writing the format into @format, and the position
434  * into @cur, if the respective parameters are non-NULL.
435  */
436 void
437 gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
438 {
439   GstStructure *structure;
440
441   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
442
443   structure = GST_QUERY_STRUCTURE (query);
444   if (format)
445     *format = g_value_get_enum (gst_structure_id_get_value (structure,
446             GST_QUARK (FORMAT)));
447   if (cur)
448     *cur = g_value_get_int64 (gst_structure_id_get_value (structure,
449             GST_QUARK (CURRENT)));
450 }
451
452
453 /**
454  * gst_query_new_duration:
455  * @format: the #GstFormat for this duration query
456  *
457  * Constructs a new stream duration query object to query in the given format.
458  * Use gst_query_unref() when done with it. A duration query will give the
459  * total length of the stream.
460  *
461  * Free-function: gst_query_unref
462  *
463  * Returns: (transfer full): a new #GstQuery
464  */
465 GstQuery *
466 gst_query_new_duration (GstFormat format)
467 {
468   GstQuery *query;
469   GstStructure *structure;
470
471   structure = gst_structure_id_new (GST_QUARK (QUERY_DURATION),
472       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
473       GST_QUARK (DURATION), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
474
475   query = gst_query_new (GST_QUERY_DURATION, structure);
476
477   return query;
478 }
479
480 /**
481  * gst_query_set_duration:
482  * @query: a #GstQuery
483  * @format: the #GstFormat for the duration
484  * @duration: the duration of the stream
485  *
486  * Answer a duration query by setting the requested value in the given format.
487  */
488 void
489 gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration)
490 {
491   GstStructure *structure;
492
493   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
494
495   structure = GST_QUERY_STRUCTURE (query);
496   gst_structure_id_set (structure,
497       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
498       GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL);
499 }
500
501 /**
502  * gst_query_parse_duration:
503  * @query: a #GstQuery
504  * @format: (out) (allow-none): the storage for the #GstFormat of the duration
505  *     value, or NULL.
506  * @duration: (out) (allow-none): the storage for the total duration, or NULL.
507  *
508  * Parse a duration query answer. Write the format of the duration into @format,
509  * and the value into @duration, if the respective variables are non-NULL.
510  */
511 void
512 gst_query_parse_duration (GstQuery * query, GstFormat * format,
513     gint64 * duration)
514 {
515   GstStructure *structure;
516
517   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
518
519   structure = GST_QUERY_STRUCTURE (query);
520   if (format)
521     *format = g_value_get_enum (gst_structure_id_get_value (structure,
522             GST_QUARK (FORMAT)));
523   if (duration)
524     *duration = g_value_get_int64 (gst_structure_id_get_value (structure,
525             GST_QUARK (DURATION)));
526 }
527
528 /**
529  * gst_query_new_latency:
530  *
531  * Constructs a new latency query object.
532  * Use gst_query_unref() when done with it. A latency query is usually performed
533  * by sinks to compensate for additional latency introduced by elements in the
534  * pipeline.
535  *
536  * Free-function: gst_query_unref
537  *
538  * Returns: (transfer full): a #GstQuery
539  *
540  * Since: 0.10.12
541  */
542 GstQuery *
543 gst_query_new_latency (void)
544 {
545   GstQuery *query;
546   GstStructure *structure;
547
548   structure = gst_structure_id_new (GST_QUARK (QUERY_LATENCY),
549       GST_QUARK (LIVE), G_TYPE_BOOLEAN, FALSE,
550       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
551       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (-1), NULL);
552
553   query = gst_query_new (GST_QUERY_LATENCY, structure);
554
555   return query;
556 }
557
558 /**
559  * gst_query_set_latency:
560  * @query: a #GstQuery
561  * @live: if there is a live element upstream
562  * @min_latency: the minimal latency of the live element
563  * @max_latency: the maximal latency of the live element
564  *
565  * Answer a latency query by setting the requested values in the given format.
566  *
567  * Since: 0.10.12
568  */
569 void
570 gst_query_set_latency (GstQuery * query, gboolean live,
571     GstClockTime min_latency, GstClockTime max_latency)
572 {
573   GstStructure *structure;
574
575   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
576
577   structure = GST_QUERY_STRUCTURE (query);
578   gst_structure_id_set (structure,
579       GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
580       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, min_latency,
581       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, max_latency, NULL);
582 }
583
584 /**
585  * gst_query_parse_latency:
586  * @query: a #GstQuery
587  * @live: (out) (allow-none): storage for live or NULL
588  * @min_latency: (out) (allow-none): the storage for the min latency or NULL
589  * @max_latency: (out) (allow-none): the storage for the max latency or NULL
590  *
591  * Parse a latency query answer.
592  *
593  * Since: 0.10.12
594  */
595 void
596 gst_query_parse_latency (GstQuery * query, gboolean * live,
597     GstClockTime * min_latency, GstClockTime * max_latency)
598 {
599   GstStructure *structure;
600
601   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
602
603   structure = GST_QUERY_STRUCTURE (query);
604   if (live)
605     *live =
606         g_value_get_boolean (gst_structure_id_get_value (structure,
607             GST_QUARK (LIVE)));
608   if (min_latency)
609     *min_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
610             GST_QUARK (MIN_LATENCY)));
611   if (max_latency)
612     *max_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
613             GST_QUARK (MAX_LATENCY)));
614 }
615
616 /**
617  * gst_query_new_convert:
618  * @src_format: the source #GstFormat for the new query
619  * @value: the value to convert
620  * @dest_format: the target #GstFormat
621  *
622  * Constructs a new convert query object. Use gst_query_unref()
623  * when done with it. A convert query is used to ask for a conversion between
624  * one format and another.
625  *
626  * Free-function: gst_query_unref
627  *
628  * Returns: (transfer full): a #GstQuery
629  */
630 GstQuery *
631 gst_query_new_convert (GstFormat src_format, gint64 value,
632     GstFormat dest_format)
633 {
634   GstQuery *query;
635   GstStructure *structure;
636
637   structure = gst_structure_id_new (GST_QUARK (QUERY_CONVERT),
638       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
639       GST_QUARK (SRC_VALUE), G_TYPE_INT64, value,
640       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
641       GST_QUARK (DEST_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
642
643   query = gst_query_new (GST_QUERY_CONVERT, structure);
644
645   return query;
646 }
647
648 /**
649  * gst_query_set_convert:
650  * @query: a #GstQuery
651  * @src_format: the source #GstFormat
652  * @src_value: the source value
653  * @dest_format: the destination #GstFormat
654  * @dest_value: the destination value
655  *
656  * Answer a convert query by setting the requested values.
657  */
658 void
659 gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value,
660     GstFormat dest_format, gint64 dest_value)
661 {
662   GstStructure *structure;
663
664   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
665
666   structure = GST_QUERY_STRUCTURE (query);
667   gst_structure_id_set (structure,
668       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
669       GST_QUARK (SRC_VALUE), G_TYPE_INT64, src_value,
670       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
671       GST_QUARK (DEST_VALUE), G_TYPE_INT64, dest_value, NULL);
672 }
673
674 /**
675  * gst_query_parse_convert:
676  * @query: a #GstQuery
677  * @src_format: (out) (allow-none): the storage for the #GstFormat of the
678  *     source value, or NULL
679  * @src_value: (out) (allow-none): the storage for the source value, or NULL
680  * @dest_format: (out) (allow-none): the storage for the #GstFormat of the
681  *     destination value, or NULL
682  * @dest_value: (out) (allow-none): the storage for the destination value,
683  *     or NULL
684  *
685  * Parse a convert query answer. Any of @src_format, @src_value, @dest_format,
686  * and @dest_value may be NULL, in which case that value is omitted.
687  */
688 void
689 gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
690     gint64 * src_value, GstFormat * dest_format, gint64 * dest_value)
691 {
692   GstStructure *structure;
693
694   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
695
696   structure = GST_QUERY_STRUCTURE (query);
697   if (src_format)
698     *src_format = g_value_get_enum (gst_structure_id_get_value (structure,
699             GST_QUARK (SRC_FORMAT)));
700   if (src_value)
701     *src_value = g_value_get_int64 (gst_structure_id_get_value (structure,
702             GST_QUARK (SRC_VALUE)));
703   if (dest_format)
704     *dest_format = g_value_get_enum (gst_structure_id_get_value (structure,
705             GST_QUARK (DEST_FORMAT)));
706   if (dest_value)
707     *dest_value = g_value_get_int64 (gst_structure_id_get_value (structure,
708             GST_QUARK (DEST_VALUE)));
709 }
710
711 /**
712  * gst_query_new_segment:
713  * @format: the #GstFormat for the new query
714  *
715  * Constructs a new segment query object. Use gst_query_unref()
716  * when done with it. A segment query is used to discover information about the
717  * currently configured segment for playback.
718  *
719  * Free-function: gst_query_unref
720  *
721  * Returns: (transfer full): a new #GstQuery
722  */
723 GstQuery *
724 gst_query_new_segment (GstFormat format)
725 {
726   GstQuery *query;
727   GstStructure *structure;
728
729   structure = gst_structure_id_new (GST_QUARK (QUERY_SEGMENT),
730       GST_QUARK (RATE), G_TYPE_DOUBLE, (gdouble) 0.0,
731       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
732       GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
733       GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
734
735   query = gst_query_new (GST_QUERY_SEGMENT, structure);
736
737   return query;
738 }
739
740 /**
741  * gst_query_set_segment:
742  * @query: a #GstQuery
743  * @rate: the rate of the segment
744  * @format: the #GstFormat of the segment values (@start_value and @stop_value)
745  * @start_value: the start value
746  * @stop_value: the stop value
747  *
748  * Answer a segment query by setting the requested values. The normal
749  * playback segment of a pipeline is 0 to duration at the default rate of
750  * 1.0. If a seek was performed on the pipeline to play a different
751  * segment, this query will return the range specified in the last seek.
752  *
753  * @start_value and @stop_value will respectively contain the configured
754  * playback range start and stop values expressed in @format.
755  * The values are always between 0 and the duration of the media and
756  * @start_value <= @stop_value. @rate will contain the playback rate. For
757  * negative rates, playback will actually happen from @stop_value to
758  * @start_value.
759  */
760 void
761 gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format,
762     gint64 start_value, gint64 stop_value)
763 {
764   GstStructure *structure;
765
766   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
767
768   structure = GST_QUERY_STRUCTURE (query);
769   gst_structure_id_set (structure,
770       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
771       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
772       GST_QUARK (START_VALUE), G_TYPE_INT64, start_value,
773       GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop_value, NULL);
774 }
775
776 /**
777  * gst_query_parse_segment:
778  * @query: a #GstQuery
779  * @rate: (out) (allow-none): the storage for the rate of the segment, or NULL
780  * @format: (out) (allow-none): the storage for the #GstFormat of the values,
781  *     or NULL
782  * @start_value: (out) (allow-none): the storage for the start value, or NULL
783  * @stop_value: (out) (allow-none): the storage for the stop value, or NULL
784  *
785  * Parse a segment query answer. Any of @rate, @format, @start_value, and
786  * @stop_value may be NULL, which will cause this value to be omitted.
787  *
788  * See gst_query_set_segment() for an explanation of the function arguments.
789  */
790 void
791 gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
792     gint64 * start_value, gint64 * stop_value)
793 {
794   GstStructure *structure;
795
796   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
797
798   structure = GST_QUERY_STRUCTURE (query);
799   if (rate)
800     *rate = g_value_get_double (gst_structure_id_get_value (structure,
801             GST_QUARK (RATE)));
802   if (format)
803     *format = g_value_get_enum (gst_structure_id_get_value (structure,
804             GST_QUARK (FORMAT)));
805   if (start_value)
806     *start_value = g_value_get_int64 (gst_structure_id_get_value (structure,
807             GST_QUARK (START_VALUE)));
808   if (stop_value)
809     *stop_value = g_value_get_int64 (gst_structure_id_get_value (structure,
810             GST_QUARK (STOP_VALUE)));
811 }
812
813 /**
814  * gst_query_new_custom:
815  * @type: the query type
816  * @structure: a structure for the query
817  *
818  * Constructs a new custom query object. Use gst_query_unref()
819  * when done with it.
820  *
821  * Free-function: gst_query_unref
822  *
823  * Returns: (transfer full): a new #GstQuery
824  */
825 GstQuery *
826 gst_query_new_custom (GstQueryType type, GstStructure * structure)
827 {
828   g_return_val_if_fail (gst_query_type_get_details (type) != NULL, NULL);
829   g_return_val_if_fail (structure != NULL, NULL);
830
831   return gst_query_new (type, structure);
832 }
833
834 /**
835  * gst_query_get_structure:
836  * @query: a #GstQuery
837  *
838  * Get the structure of a query.
839  *
840  * Returns: (transfer none): the #GstStructure of the query. The structure is
841  *     still owned by the query and will therefore be freed when the query
842  *     is unreffed.
843  */
844 const GstStructure *
845 gst_query_get_structure (GstQuery * query)
846 {
847   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
848
849   return GST_QUERY_STRUCTURE (query);
850 }
851
852 /**
853  * gst_query_writable_structure:
854  * @query: a #GstQuery
855  *
856  * Get the structure of a query.
857  *
858  * Returns: (transfer none): the #GstStructure of the query. The structure is
859  *     still owned by the query and will therefore be freed when the query
860  *     is unreffed.
861  */
862 GstStructure *
863 gst_query_writable_structure (GstQuery * query)
864 {
865   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
866   g_return_val_if_fail (gst_query_is_writable (query), NULL);
867
868   return GST_QUERY_STRUCTURE (query);
869 }
870
871 /**
872  * gst_query_new_seeking:
873  * @format: the default #GstFormat for the new query
874  *
875  * Constructs a new query object for querying seeking properties of
876  * the stream.
877  *
878  * Free-function: gst_query_unref
879  *
880  * Returns: (transfer full): a new #GstQuery
881  */
882 GstQuery *
883 gst_query_new_seeking (GstFormat format)
884 {
885   GstQuery *query;
886   GstStructure *structure;
887
888   structure = gst_structure_id_new (GST_QUARK (QUERY_SEEKING),
889       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
890       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, FALSE,
891       GST_QUARK (SEGMENT_START), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
892       GST_QUARK (SEGMENT_END), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
893
894   query = gst_query_new (GST_QUERY_SEEKING, structure);
895
896   return query;
897 }
898
899 /**
900  * gst_query_set_seeking:
901  * @query: a #GstQuery
902  * @format: the format to set for the @segment_start and @segment_end values
903  * @seekable: the seekable flag to set
904  * @segment_start: the segment_start to set
905  * @segment_end: the segment_end to set
906  *
907  * Set the seeking query result fields in @query.
908  */
909 void
910 gst_query_set_seeking (GstQuery * query, GstFormat format,
911     gboolean seekable, gint64 segment_start, gint64 segment_end)
912 {
913   GstStructure *structure;
914
915   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
916   g_return_if_fail (gst_query_is_writable (query));
917
918   structure = GST_QUERY_STRUCTURE (query);
919   gst_structure_id_set (structure,
920       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
921       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable,
922       GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start,
923       GST_QUARK (SEGMENT_END), G_TYPE_INT64, segment_end, NULL);
924 }
925
926 /**
927  * gst_query_parse_seeking:
928  * @query: a GST_QUERY_SEEKING type query #GstQuery
929  * @format: (out) (allow-none): the format to set for the @segment_start
930  *     and @segment_end values, or NULL
931  * @seekable: (out) (allow-none): the seekable flag to set, or NULL
932  * @segment_start: (out) (allow-none): the segment_start to set, or NULL
933  * @segment_end: (out) (allow-none): the segment_end to set, or NULL
934  *
935  * Parse a seeking query, writing the format into @format, and
936  * other results into the passed parameters, if the respective parameters
937  * are non-NULL
938  */
939 void
940 gst_query_parse_seeking (GstQuery * query, GstFormat * format,
941     gboolean * seekable, gint64 * segment_start, gint64 * segment_end)
942 {
943   GstStructure *structure;
944
945   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
946
947   structure = GST_QUERY_STRUCTURE (query);
948   if (format)
949     *format = g_value_get_enum (gst_structure_id_get_value (structure,
950             GST_QUARK (FORMAT)));
951   if (seekable)
952     *seekable = g_value_get_boolean (gst_structure_id_get_value (structure,
953             GST_QUARK (SEEKABLE)));
954   if (segment_start)
955     *segment_start = g_value_get_int64 (gst_structure_id_get_value (structure,
956             GST_QUARK (SEGMENT_START)));
957   if (segment_end)
958     *segment_end = g_value_get_int64 (gst_structure_id_get_value (structure,
959             GST_QUARK (SEGMENT_END)));
960 }
961
962 /**
963  * gst_query_new_formats:
964  *
965  * Constructs a new query object for querying formats of
966  * the stream.
967  *
968  * Free-function: gst_query_unref
969  *
970  * Returns: (transfer full): a new #GstQuery
971  *
972  * Since: 0.10.4
973  */
974 GstQuery *
975 gst_query_new_formats (void)
976 {
977   GstQuery *query;
978   GstStructure *structure;
979
980   structure = gst_structure_id_empty_new (GST_QUARK (QUERY_FORMATS));
981   query = gst_query_new (GST_QUERY_FORMATS, structure);
982
983   return query;
984 }
985
986 static void
987 gst_query_list_add_format (GValue * list, GstFormat format)
988 {
989   GValue item = { 0, };
990
991   g_value_init (&item, GST_TYPE_FORMAT);
992   g_value_set_enum (&item, format);
993   gst_value_list_append_value (list, &item);
994   g_value_unset (&item);
995 }
996
997 /**
998  * gst_query_set_formats:
999  * @query: a #GstQuery
1000  * @n_formats: the number of formats to set.
1001  * @...: A number of @GstFormats equal to @n_formats.
1002  *
1003  * Set the formats query result fields in @query. The number of formats passed
1004  * must be equal to @n_formats.
1005  */
1006 void
1007 gst_query_set_formats (GstQuery * query, gint n_formats, ...)
1008 {
1009   va_list ap;
1010   GValue list = { 0, };
1011   gint i;
1012   GstStructure *structure;
1013
1014   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
1015   g_return_if_fail (gst_query_is_writable (query));
1016
1017   g_value_init (&list, GST_TYPE_LIST);
1018
1019   va_start (ap, n_formats);
1020   for (i = 0; i < n_formats; i++) {
1021     gst_query_list_add_format (&list, va_arg (ap, GstFormat));
1022   }
1023   va_end (ap);
1024
1025   structure = GST_QUERY_STRUCTURE (query);
1026   gst_structure_set_value (structure, "formats", &list);
1027
1028   g_value_unset (&list);
1029
1030 }
1031
1032 /**
1033  * gst_query_set_formatsv:
1034  * @query: a #GstQuery
1035  * @n_formats: the number of formats to set.
1036  * @formats: (in) (array length=n_formats): an array containing @n_formats
1037  *     @GstFormat values.
1038  *
1039  * Set the formats query result fields in @query. The number of formats passed
1040  * in the @formats array must be equal to @n_formats.
1041  *
1042  * Since: 0.10.4
1043  */
1044 void
1045 gst_query_set_formatsv (GstQuery * query, gint n_formats,
1046     const GstFormat * formats)
1047 {
1048   GValue list = { 0, };
1049   gint i;
1050   GstStructure *structure;
1051
1052   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
1053   g_return_if_fail (gst_query_is_writable (query));
1054
1055   g_value_init (&list, GST_TYPE_LIST);
1056   for (i = 0; i < n_formats; i++) {
1057     gst_query_list_add_format (&list, formats[i]);
1058   }
1059   structure = GST_QUERY_STRUCTURE (query);
1060   gst_structure_set_value (structure, "formats", &list);
1061
1062   g_value_unset (&list);
1063 }
1064
1065 /**
1066  * gst_query_parse_n_formats:
1067  * @query: a #GstQuery
1068  * @n_formats: (out): the number of formats in this query.
1069  *
1070  * Parse the number of formats in the formats @query.
1071  *
1072  * Since: 0.10.4
1073  */
1074 void
1075 gst_query_parse_n_formats (GstQuery * query, guint * n_formats)
1076 {
1077   GstStructure *structure;
1078
1079   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
1080
1081   if (n_formats) {
1082     const GValue *list;
1083
1084     structure = GST_QUERY_STRUCTURE (query);
1085     list = gst_structure_get_value (structure, "formats");
1086     if (list == NULL)
1087       *n_formats = 0;
1088     else
1089       *n_formats = gst_value_list_get_size (list);
1090   }
1091 }
1092
1093 /**
1094  * gst_query_parse_nth_format:
1095  * @query: a #GstQuery
1096  * @nth: (out): the nth format to retrieve.
1097  * @format: (out): a pointer to store the nth format
1098  *
1099  * Parse the format query and retrieve the @nth format from it into
1100  * @format. If the list contains less elements than @nth, @format will be
1101  * set to GST_FORMAT_UNDEFINED.
1102  */
1103 void
1104 gst_query_parse_nth_format (GstQuery * query, guint nth, GstFormat * format)
1105 {
1106   GstStructure *structure;
1107
1108   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
1109
1110   if (format) {
1111     const GValue *list;
1112
1113     structure = GST_QUERY_STRUCTURE (query);
1114     list = gst_structure_get_value (structure, "formats");
1115     if (list == NULL) {
1116       *format = GST_FORMAT_UNDEFINED;
1117     } else {
1118       if (nth < gst_value_list_get_size (list)) {
1119         *format = g_value_get_enum (gst_value_list_get_value (list, nth));
1120       } else
1121         *format = GST_FORMAT_UNDEFINED;
1122     }
1123   }
1124 }
1125
1126 /**
1127  * gst_query_new_buffering
1128  * @format: the default #GstFormat for the new query
1129  *
1130  * Constructs a new query object for querying the buffering status of
1131  * a stream.
1132  *
1133  * Free-function: gst_query_unref
1134  *
1135  * Returns: (transfer full): a new #GstQuery
1136  *
1137  * Since: 0.10.20
1138  */
1139 GstQuery *
1140 gst_query_new_buffering (GstFormat format)
1141 {
1142   GstQuery *query;
1143   GstStructure *structure;
1144
1145   /* by default, we configure the answer as no buffering with a 100% buffering
1146    * progress */
1147   structure = gst_structure_id_new (GST_QUARK (QUERY_BUFFERING),
1148       GST_QUARK (BUSY), G_TYPE_BOOLEAN, FALSE,
1149       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, 100,
1150       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
1151       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
1152       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
1153       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, G_GINT64_CONSTANT (0),
1154       GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
1155       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1156       GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
1157       GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
1158
1159   query = gst_query_new (GST_QUERY_BUFFERING, structure);
1160
1161   return query;
1162 }
1163
1164 /**
1165  * gst_query_set_buffering_percent
1166  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1167  * @busy: if buffering is busy
1168  * @percent: a buffering percent
1169  *
1170  * Set the percentage of buffered data. This is a value between 0 and 100.
1171  * The @busy indicator is %TRUE when the buffering is in progress.
1172  *
1173  * Since: 0.10.20
1174  */
1175 void
1176 gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent)
1177 {
1178   GstStructure *structure;
1179
1180   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1181   g_return_if_fail (gst_query_is_writable (query));
1182   g_return_if_fail (percent >= 0 && percent <= 100);
1183
1184   structure = GST_QUERY_STRUCTURE (query);
1185   gst_structure_id_set (structure,
1186       GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy,
1187       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL);
1188 }
1189
1190 /**
1191  * gst_query_parse_buffering_percent
1192  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1193  * @busy: (out) (allow-none): if buffering is busy, or NULL
1194  * @percent: (out) (allow-none): a buffering percent, or NULL
1195  *
1196  * Get the percentage of buffered data. This is a value between 0 and 100.
1197  * The @busy indicator is %TRUE when the buffering is in progress.
1198  *
1199  * Since: 0.10.20
1200  */
1201 void
1202 gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy,
1203     gint * percent)
1204 {
1205   GstStructure *structure;
1206
1207   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1208
1209   structure = GST_QUERY_STRUCTURE (query);
1210   if (busy)
1211     *busy = g_value_get_boolean (gst_structure_id_get_value (structure,
1212             GST_QUARK (BUSY)));
1213   if (percent)
1214     *percent = g_value_get_int (gst_structure_id_get_value (structure,
1215             GST_QUARK (BUFFER_PERCENT)));
1216 }
1217
1218 /**
1219  * gst_query_set_buffering_stats:
1220  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1221  * @mode: a buffering mode
1222  * @avg_in: the average input rate
1223  * @avg_out: the average output rate
1224  * @buffering_left: amount of buffering time left
1225  *
1226  * Configures the buffering stats values in @query.
1227  *
1228  * Since: 0.10.20
1229  */
1230 void
1231 gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode,
1232     gint avg_in, gint avg_out, gint64 buffering_left)
1233 {
1234   GstStructure *structure;
1235
1236   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1237   g_return_if_fail (gst_query_is_writable (query));
1238
1239   structure = GST_QUERY_STRUCTURE (query);
1240   gst_structure_id_set (structure,
1241       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
1242       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
1243       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
1244       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
1245 }
1246
1247 /**
1248  * gst_query_parse_buffering_stats:
1249  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1250  * @mode: (out) (allow-none): a buffering mode, or NULL
1251  * @avg_in: (out) (allow-none): the average input rate, or NULL
1252  * @avg_out: (out) (allow-none): the average output rat, or NULLe
1253  * @buffering_left: (out) (allow-none): amount of buffering time left, or NULL
1254  *
1255  * Extracts the buffering stats values from @query.
1256  *
1257  * Since: 0.10.20
1258  */
1259 void
1260 gst_query_parse_buffering_stats (GstQuery * query,
1261     GstBufferingMode * mode, gint * avg_in, gint * avg_out,
1262     gint64 * buffering_left)
1263 {
1264   GstStructure *structure;
1265
1266   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1267
1268   structure = GST_QUERY_STRUCTURE (query);
1269   if (mode)
1270     *mode = g_value_get_enum (gst_structure_id_get_value (structure,
1271             GST_QUARK (BUFFERING_MODE)));
1272   if (avg_in)
1273     *avg_in = g_value_get_int (gst_structure_id_get_value (structure,
1274             GST_QUARK (AVG_IN_RATE)));
1275   if (avg_out)
1276     *avg_out = g_value_get_int (gst_structure_id_get_value (structure,
1277             GST_QUARK (AVG_OUT_RATE)));
1278   if (buffering_left)
1279     *buffering_left =
1280         g_value_get_int64 (gst_structure_id_get_value (structure,
1281             GST_QUARK (BUFFERING_LEFT)));
1282 }
1283
1284
1285 /**
1286  * gst_query_set_buffering_range:
1287  * @query: a #GstQuery
1288  * @format: the format to set for the @start and @stop values
1289  * @start: the start to set
1290  * @stop: the stop to set
1291  * @estimated_total: estimated total amount of download time
1292  *
1293  * Set the available query result fields in @query.
1294  *
1295  * Since: 0.10.20
1296  */
1297 void
1298 gst_query_set_buffering_range (GstQuery * query, GstFormat format,
1299     gint64 start, gint64 stop, gint64 estimated_total)
1300 {
1301   GstStructure *structure;
1302
1303   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1304   g_return_if_fail (gst_query_is_writable (query));
1305
1306   structure = GST_QUERY_STRUCTURE (query);
1307   gst_structure_id_set (structure,
1308       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1309       GST_QUARK (START_VALUE), G_TYPE_INT64, start,
1310       GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop,
1311       GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, estimated_total, NULL);
1312 }
1313
1314 /**
1315  * gst_query_parse_buffering_range:
1316  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1317  * @format: (out) (allow-none): the format to set for the @segment_start
1318  *     and @segment_end values, or NULL
1319  * @start: (out) (allow-none): the start to set, or NULL
1320  * @stop: (out) (allow-none): the stop to set, or NULL
1321  * @estimated_total: (out) (allow-none): estimated total amount of download
1322  *     time, or NULL
1323  *
1324  * Parse an available query, writing the format into @format, and
1325  * other results into the passed parameters, if the respective parameters
1326  * are non-NULL
1327  *
1328  * Since: 0.10.20
1329  */
1330 void
1331 gst_query_parse_buffering_range (GstQuery * query, GstFormat * format,
1332     gint64 * start, gint64 * stop, gint64 * estimated_total)
1333 {
1334   GstStructure *structure;
1335
1336   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1337
1338   structure = GST_QUERY_STRUCTURE (query);
1339   if (format)
1340     *format = g_value_get_enum (gst_structure_id_get_value (structure,
1341             GST_QUARK (FORMAT)));
1342   if (start)
1343     *start = g_value_get_int64 (gst_structure_id_get_value (structure,
1344             GST_QUARK (START_VALUE)));
1345   if (stop)
1346     *stop = g_value_get_int64 (gst_structure_id_get_value (structure,
1347             GST_QUARK (STOP_VALUE)));
1348   if (estimated_total)
1349     *estimated_total =
1350         g_value_get_int64 (gst_structure_id_get_value (structure,
1351             GST_QUARK (ESTIMATED_TOTAL)));
1352 }
1353
1354 /**
1355  * gst_query_add_buffering_range
1356  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1357  * @start: start position of the range
1358  * @stop: stop position of the range
1359  *
1360  * Set the buffering-ranges array field in @query. The current last
1361  * start position of the array should be inferior to @start.
1362  *
1363  * Returns: a #gboolean indicating if the range was added or not.
1364  *
1365  * Since: 0.10.31
1366  */
1367 gboolean
1368 gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop)
1369 {
1370   GValueArray *array;
1371   GValue *last_array_value;
1372   const GValue *value;
1373   GValue range_value = { 0 };
1374   GstStructure *structure;
1375
1376   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE);
1377   g_return_val_if_fail (gst_query_is_writable (query), FALSE);
1378
1379   if (G_UNLIKELY (start >= stop))
1380     return FALSE;
1381
1382   structure = GST_QUERY_STRUCTURE (query);
1383   value = gst_structure_id_get_value (structure, GST_QUARK (BUFFERING_RANGES));
1384   if (value) {
1385     array = (GValueArray *) g_value_get_boxed (value);
1386     last_array_value = g_value_array_get_nth (array, array->n_values - 1);
1387     if (G_UNLIKELY (start <= gst_value_get_int64_range_min (last_array_value)))
1388       return FALSE;
1389   } else {
1390     GValue new_array_val = { 0, };
1391
1392     array = g_value_array_new (0);
1393
1394     g_value_init (&new_array_val, G_TYPE_VALUE_ARRAY);
1395     g_value_take_boxed (&new_array_val, array);
1396
1397     /* set the value array only once, so we then modify (append to) the
1398      * existing value array owned by the GstStructure / the field's GValue */
1399     gst_structure_id_take_value (structure, GST_QUARK (BUFFERING_RANGES),
1400         &new_array_val);
1401   }
1402
1403   g_value_init (&range_value, GST_TYPE_INT64_RANGE);
1404   gst_value_set_int64_range (&range_value, start, stop);
1405   g_value_array_append (array, &range_value);
1406   /* skip the g_value_unset(&range_value) here, we know it's not needed */
1407
1408   return TRUE;
1409 }
1410
1411 /**
1412  * gst_query_get_n_buffering_ranges
1413  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1414  *
1415  * Retrieve the number of values currently stored in the
1416  * buffered-ranges array of the query's structure.
1417  *
1418  * Returns: the range array size as a #guint.
1419  *
1420  * Since: 0.10.31
1421  */
1422 guint
1423 gst_query_get_n_buffering_ranges (GstQuery * query)
1424 {
1425   GValueArray *array;
1426   const GValue *value;
1427   guint size = 0;
1428   GstStructure *structure;
1429
1430   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, 0);
1431
1432   structure = GST_QUERY_STRUCTURE (query);
1433   value = gst_structure_id_get_value (structure, GST_QUARK (BUFFERING_RANGES));
1434   if (value) {
1435     array = (GValueArray *) g_value_get_boxed (value);
1436     size = array->n_values;
1437   }
1438   return size;
1439 }
1440
1441
1442 /**
1443  * gst_query_parse_nth_buffering_range
1444  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1445  * @index: position in the buffered-ranges array to read
1446  * @start: (out) (allow-none): the start position to set, or NULL
1447  * @stop: (out) (allow-none): the stop position to set, or NULL
1448  *
1449  * Parse an available query and get the start and stop values stored
1450  * at the @index of the buffered ranges array.
1451  *
1452  * Returns: a #gboolean indicating if the parsing succeeded.
1453  *
1454  * Since: 0.10.31
1455  */
1456 gboolean
1457 gst_query_parse_nth_buffering_range (GstQuery * query, guint index,
1458     gint64 * start, gint64 * stop)
1459 {
1460   const GValue *value;
1461   GValueArray *ranges;
1462   GValue *range_value;
1463   gboolean ret = FALSE;
1464   GstStructure *structure;
1465
1466   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, ret);
1467
1468   structure = GST_QUERY_STRUCTURE (query);
1469   value = gst_structure_id_get_value (structure, GST_QUARK (BUFFERING_RANGES));
1470   ranges = (GValueArray *) g_value_get_boxed (value);
1471   range_value = g_value_array_get_nth (ranges, index);
1472   if (range_value) {
1473     if (start)
1474       *start = gst_value_get_int64_range_min (range_value);
1475     if (stop)
1476       *stop = gst_value_get_int64_range_max (range_value);
1477     ret = TRUE;
1478   }
1479
1480   return ret;
1481 }
1482
1483
1484 /**
1485  * gst_query_new_uri:
1486  *
1487  * Constructs a new query URI query object. Use gst_query_unref()
1488  * when done with it. An URI query is used to query the current URI
1489  * that is used by the source or sink.
1490  *
1491  * Free-function: gst_query_unref
1492  *
1493  * Returns: (transfer full): a new #GstQuery
1494  *
1495  * Since: 0.10.22
1496  */
1497 GstQuery *
1498 gst_query_new_uri (void)
1499 {
1500   GstQuery *query;
1501   GstStructure *structure;
1502
1503   structure = gst_structure_id_new (GST_QUARK (QUERY_URI),
1504       GST_QUARK (URI), G_TYPE_STRING, NULL, NULL);
1505
1506   query = gst_query_new (GST_QUERY_URI, structure);
1507
1508   return query;
1509 }
1510
1511 /**
1512  * gst_query_set_uri:
1513  * @query: a #GstQuery with query type GST_QUERY_URI
1514  * @uri: the URI to set
1515  *
1516  * Answer a URI query by setting the requested URI.
1517  *
1518  * Since: 0.10.22
1519  */
1520 void
1521 gst_query_set_uri (GstQuery * query, const gchar * uri)
1522 {
1523   GstStructure *structure;
1524
1525   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1526   g_return_if_fail (gst_query_is_writable (query));
1527   g_return_if_fail (gst_uri_is_valid (uri));
1528
1529   structure = GST_QUERY_STRUCTURE (query);
1530   gst_structure_id_set (structure, GST_QUARK (URI), G_TYPE_STRING, uri, NULL);
1531 }
1532
1533 /**
1534  * gst_query_parse_uri:
1535  * @query: a #GstQuery
1536  * @uri: (out callee-allocates) (allow-none): the storage for the current URI
1537  *     (may be NULL)
1538  *
1539  * Parse an URI query, writing the URI into @uri as a newly
1540  * allocated string, if the respective parameters are non-NULL.
1541  * Free the string with g_free() after usage.
1542  *
1543  * Since: 0.10.22
1544  */
1545 void
1546 gst_query_parse_uri (GstQuery * query, gchar ** uri)
1547 {
1548   GstStructure *structure;
1549
1550   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1551
1552   structure = GST_QUERY_STRUCTURE (query);
1553   if (uri)
1554     *uri = g_value_dup_string (gst_structure_id_get_value (structure,
1555             GST_QUARK (URI)));
1556 }
1557
1558 /**
1559  * gst_query_new_allocation
1560  * @caps: the negotiated caps
1561  * @need_pool: return a pool
1562  *
1563  * Constructs a new query object for querying the allocation properties.
1564  *
1565  * Free-function: gst_query_unref
1566  *
1567  * Returns: (transfer full): a new #GstQuery
1568  */
1569 GstQuery *
1570 gst_query_new_allocation (GstCaps * caps, gboolean need_pool)
1571 {
1572   GstQuery *query;
1573   GstStructure *structure;
1574
1575   structure = gst_structure_id_new (GST_QUARK (QUERY_ALLOCATION),
1576       GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
1577       GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool,
1578       GST_QUARK (PREFIX), G_TYPE_UINT, 0,
1579       GST_QUARK (ALIGN), G_TYPE_UINT, 1,
1580       GST_QUARK (SIZE), G_TYPE_UINT, 0,
1581       GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, NULL, NULL);
1582
1583   query = gst_query_new (GST_QUERY_ALLOCATION, structure);
1584
1585   return query;
1586 }
1587
1588 void
1589 gst_query_parse_allocation (GstQuery * query, GstCaps ** caps,
1590     gboolean * need_pool)
1591 {
1592   GstStructure *structure;
1593
1594   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1595
1596   structure = GST_QUERY_STRUCTURE (query);
1597   gst_structure_id_get (structure,
1598       GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
1599       GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
1600 }
1601
1602 /**
1603  * gst_query_set_allocation_params
1604  * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
1605  * @alignment: the alignment
1606  * @prefix: the prefix
1607  * @size: the size
1608  * @pool: the #GstBufferPool
1609  *
1610  * Set the allocation parameters in @query.
1611  */
1612 void
1613 gst_query_set_allocation_params (GstQuery * query, guint size,
1614     guint min_buffers, guint max_buffers, guint prefix,
1615     guint alignment, GstBufferPool * pool)
1616 {
1617   GstStructure *structure;
1618
1619   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1620   g_return_if_fail (gst_query_is_writable (query));
1621
1622   structure = GST_QUERY_STRUCTURE (query);
1623   gst_structure_id_set (structure,
1624       GST_QUARK (SIZE), G_TYPE_UINT, size,
1625       GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
1626       GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers,
1627       GST_QUARK (PREFIX), G_TYPE_UINT, prefix,
1628       GST_QUARK (ALIGN), G_TYPE_UINT, alignment,
1629       GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, pool, NULL);
1630 }
1631
1632 /**
1633  * gst_query_parse_allocation_params
1634  * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
1635  * @alignment: the alignment
1636  * @prefix: the prefix
1637  * @size: the size
1638  * @pool: the #GstBufferPool
1639  *
1640  * Get the allocation parameters in @query.
1641  */
1642 void
1643 gst_query_parse_allocation_params (GstQuery * query, guint * size,
1644     guint * min_buffers, guint * max_buffers, guint * prefix,
1645     guint * alignment, GstBufferPool ** pool)
1646 {
1647   GstStructure *structure;
1648
1649   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1650
1651   structure = GST_QUERY_STRUCTURE (query);
1652   gst_structure_id_get (structure,
1653       GST_QUARK (SIZE), G_TYPE_UINT, size,
1654       GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
1655       GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers,
1656       GST_QUARK (PREFIX), G_TYPE_UINT, prefix,
1657       GST_QUARK (ALIGN), G_TYPE_UINT, alignment,
1658       GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, pool, NULL);
1659 }
1660
1661 /**
1662  * gst_query_add_allocation_meta
1663  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1664  * @api: the metadata API
1665  *
1666  * Add @api as aone of the supported metadata API to @query.
1667  */
1668 void
1669 gst_query_add_allocation_meta (GstQuery * query, const gchar * api)
1670 {
1671   GValueArray *array;
1672   const GValue *value;
1673   GValue api_value = { 0 };
1674   GstStructure *structure;
1675
1676   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1677   g_return_if_fail (gst_query_is_writable (query));
1678
1679   structure = GST_QUERY_STRUCTURE (query);
1680   value = gst_structure_id_get_value (structure, GST_QUARK (META));
1681   if (value) {
1682     array = (GValueArray *) g_value_get_boxed (value);
1683   } else {
1684     GValue new_array_val = { 0, };
1685
1686     array = g_value_array_new (0);
1687
1688     g_value_init (&new_array_val, G_TYPE_VALUE_ARRAY);
1689     g_value_take_boxed (&new_array_val, array);
1690
1691     gst_structure_id_take_value (structure, GST_QUARK (META), &new_array_val);
1692   }
1693
1694   g_value_init (&api_value, G_TYPE_STRING);
1695   g_value_set_string (&api_value, api);
1696   g_value_array_append (array, &api_value);
1697   g_value_unset (&api_value);
1698 }
1699
1700 /**
1701  * gst_query_get_n_allocation_metas:
1702  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1703  *
1704  * Retrieve the number of values currently stored in the
1705  * meta API array of the query's structure.
1706  *
1707  * Returns: the metadata API array size as a #guint.
1708  */
1709 guint
1710 gst_query_get_n_allocation_metas (GstQuery * query)
1711 {
1712   GValueArray *array;
1713   const GValue *value;
1714   guint size = 0;
1715   GstStructure *structure;
1716
1717   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
1718
1719   structure = GST_QUERY_STRUCTURE (query);
1720   value = gst_structure_id_get_value (structure, GST_QUARK (META));
1721   if (value) {
1722     array = (GValueArray *) g_value_get_boxed (value);
1723     size = array->n_values;
1724   }
1725   return size;
1726 }
1727
1728 /**
1729  * gst_query_parse_nth_allocation_meta
1730  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1731  * @index: position in the metadata API array to read
1732  *
1733  * Parse an available query and get the metadata API
1734  * at @index of the metadata API array.
1735  *
1736  * Returns: a #gchar of the metadata API at @index.
1737  */
1738 const gchar *
1739 gst_query_parse_nth_allocation_meta (GstQuery * query, guint index)
1740 {
1741   const GValue *value;
1742   const gchar *ret = NULL;
1743   GstStructure *structure;
1744
1745   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, NULL);
1746
1747   structure = GST_QUERY_STRUCTURE (query);
1748   value = gst_structure_id_get_value (structure, GST_QUARK (META));
1749   if (value) {
1750     GValueArray *meta;
1751     GValue *api_value;
1752
1753     meta = (GValueArray *) g_value_get_boxed (value);
1754     api_value = g_value_array_get_nth (meta, index);
1755
1756     if (api_value)
1757       ret = g_value_get_string (api_value);
1758   }
1759   return ret;
1760 }
1761
1762 /**
1763  * gst_query_new_scheduling
1764  *
1765  * Constructs a new query object for querying the scheduling properties.
1766  *
1767  * Free-function: gst_query_unref
1768  *
1769  * Returns: (transfer full): a new #GstQuery
1770  */
1771 GstQuery *
1772 gst_query_new_scheduling (void)
1773 {
1774   GstQuery *query;
1775   GstStructure *structure;
1776
1777   structure = gst_structure_id_new (GST_QUARK (QUERY_SCHEDULING),
1778       GST_QUARK (PULL_MODE), G_TYPE_BOOLEAN, FALSE,
1779       GST_QUARK (RANDOM_ACCESS), G_TYPE_BOOLEAN, FALSE,
1780       GST_QUARK (SEQUENTIAL), G_TYPE_BOOLEAN, TRUE,
1781       GST_QUARK (MINSIZE), G_TYPE_INT, 1,
1782       GST_QUARK (MAXSIZE), G_TYPE_INT, -1,
1783       GST_QUARK (ALIGN), G_TYPE_INT, 1, NULL);
1784   query = gst_query_new (GST_QUERY_SCHEDULING, structure);
1785
1786   return query;
1787 }
1788
1789 /**
1790  * gst_query_set_scheduling
1791  * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING.
1792  * @pull_mode: if pull mode scheduling is supported
1793  * @random_access: if random access is possible
1794  * @sequential: if sequential access is recommended
1795  * @minsize: the suggested minimum size of pull requests
1796  * @maxsize the suggested maximum size of pull requests:
1797  * @align: the suggested alignment of pull requests
1798  *
1799  * Set the scheduling properties.
1800  */
1801 void
1802 gst_query_set_scheduling (GstQuery * query, gboolean pull_mode,
1803     gboolean random_access, gboolean sequential,
1804     gint minsize, gint maxsize, gint align)
1805 {
1806   GstStructure *structure;
1807
1808   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
1809   g_return_if_fail (gst_query_is_writable (query));
1810
1811   structure = GST_QUERY_STRUCTURE (query);
1812   gst_structure_id_set (structure,
1813       GST_QUARK (PULL_MODE), G_TYPE_BOOLEAN, pull_mode,
1814       GST_QUARK (RANDOM_ACCESS), G_TYPE_BOOLEAN, random_access,
1815       GST_QUARK (SEQUENTIAL), G_TYPE_BOOLEAN, sequential,
1816       GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
1817       GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
1818       GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
1819 }
1820
1821 /**
1822  * gst_query_parse_scheduling
1823  * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING.
1824  * @pull_mode: if pull mode scheduling is supported
1825  * @random_access: if random access is possible
1826  * @sequential: if sequential access is recommended
1827  * @minsize: the suggested minimum size of pull requests
1828  * @maxsize the suggested maximum size of pull requests:
1829  * @align: the suggested alignment of pull requests
1830  *
1831  * Set the scheduling properties.
1832  */
1833 void
1834 gst_query_parse_scheduling (GstQuery * query, gboolean * pull_mode,
1835     gboolean * random_access, gboolean * sequential,
1836     gint * minsize, gint * maxsize, gint * align)
1837 {
1838   GstStructure *structure;
1839
1840   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
1841
1842   structure = GST_QUERY_STRUCTURE (query);
1843   gst_structure_id_get (structure,
1844       GST_QUARK (PULL_MODE), G_TYPE_BOOLEAN, pull_mode,
1845       GST_QUARK (RANDOM_ACCESS), G_TYPE_BOOLEAN, random_access,
1846       GST_QUARK (SEQUENTIAL), G_TYPE_BOOLEAN, sequential,
1847       GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
1848       GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
1849       GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
1850 }