Suppress deprecation warnings in selected files, for g_value_array_* mostly
[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
65 /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
66  * with newer GLib versions (>= 2.31.0) */
67 #define GLIB_DISABLE_DEPRECATION_WARNINGS
68
69 #include "gst_private.h"
70 #include "gstinfo.h"
71 #include "gstquery.h"
72 #include "gstvalue.h"
73 #include "gstenumtypes.h"
74 #include "gstquark.h"
75 #include "gsturi.h"
76
77 GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
78 #define GST_CAT_DEFAULT gst_query_debug
79
80 static void gst_query_finalize (GstQuery * query);
81 static GstQuery *_gst_query_copy (GstQuery * query);
82
83 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
84 static GList *_gst_queries = NULL;
85 static GHashTable *_nick_to_query = NULL;
86 static GHashTable *_query_type_to_nick = NULL;
87 static guint32 _n_values = 1;   /* we start from 1 because 0 reserved for NONE */
88
89 static GstMiniObjectClass *parent_class = NULL;
90
91 static GstQueryTypeDefinition standard_definitions[] = {
92   {GST_QUERY_POSITION, "position", "Current position", 0},
93   {GST_QUERY_DURATION, "duration", "Total duration", 0},
94   {GST_QUERY_LATENCY, "latency", "Latency", 0},
95   {GST_QUERY_JITTER, "jitter", "Jitter", 0},
96   {GST_QUERY_RATE, "rate", "Configured rate 1000000 = 1", 0},
97   {GST_QUERY_SEEKING, "seeking", "Seeking capabilities and parameters", 0},
98   {GST_QUERY_SEGMENT, "segment", "currently configured segment", 0},
99   {GST_QUERY_CONVERT, "convert", "Converting between formats", 0},
100   {GST_QUERY_FORMATS, "formats", "Supported formats for conversion", 0},
101   {GST_QUERY_BUFFERING, "buffering", "Buffering status", 0},
102   {GST_QUERY_CUSTOM, "custom", "Custom query", 0},
103   {GST_QUERY_URI, "uri", "URI of the source or sink", 0},
104   {GST_QUERY_NONE, NULL, NULL, 0}
105 };
106
107 void
108 _gst_query_initialize (void)
109 {
110   GstQueryTypeDefinition *standards = standard_definitions;
111
112   GST_CAT_INFO (GST_CAT_GST_INIT, "init queries");
113
114   GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system");
115
116   g_static_mutex_lock (&mutex);
117   if (_nick_to_query == NULL) {
118     _nick_to_query = g_hash_table_new (g_str_hash, g_str_equal);
119     _query_type_to_nick = g_hash_table_new (NULL, NULL);
120   }
121
122   while (standards->nick) {
123     standards->quark = g_quark_from_static_string (standards->nick);
124     g_hash_table_insert (_nick_to_query, (gpointer) standards->nick, standards);
125     g_hash_table_insert (_query_type_to_nick,
126         GINT_TO_POINTER (standards->value), standards);
127
128     _gst_queries = g_list_append (_gst_queries, standards);
129     standards++;
130     _n_values++;
131   }
132   g_static_mutex_unlock (&mutex);
133
134   g_type_class_ref (gst_query_get_type ());
135 }
136
137 /**
138  * gst_query_type_get_name:
139  * @query: the query type
140  *
141  * Get a printable name for the given query type. Do not modify or free.
142  *
143  * Returns: a reference to the static name of the query.
144  */
145 const gchar *
146 gst_query_type_get_name (GstQueryType query)
147 {
148   const GstQueryTypeDefinition *def;
149
150   def = gst_query_type_get_details (query);
151
152   return def->nick;
153 }
154
155 /**
156  * gst_query_type_to_quark:
157  * @query: the query type
158  *
159  * Get the unique quark for the given query type.
160  *
161  * Returns: the quark associated with the query type
162  */
163 GQuark
164 gst_query_type_to_quark (GstQueryType query)
165 {
166   const GstQueryTypeDefinition *def;
167
168   def = gst_query_type_get_details (query);
169
170   return def->quark;
171 }
172
173 G_DEFINE_TYPE (GstQuery, gst_query, GST_TYPE_MINI_OBJECT);
174
175 static void
176 gst_query_class_init (GstQueryClass * klass)
177 {
178   parent_class = g_type_class_peek_parent (klass);
179
180   klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_query_copy;
181   klass->mini_object_class.finalize =
182       (GstMiniObjectFinalizeFunction) gst_query_finalize;
183
184 }
185
186 static void
187 gst_query_init (GstQuery * query)
188 {
189 }
190
191 static void
192 gst_query_finalize (GstQuery * query)
193 {
194   g_return_if_fail (query != NULL);
195
196   if (query->structure) {
197     gst_structure_set_parent_refcount (query->structure, NULL);
198     gst_structure_free (query->structure);
199   }
200
201 /*   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (query)); */
202 }
203
204 static GstQuery *
205 _gst_query_copy (GstQuery * query)
206 {
207   GstQuery *copy;
208
209   copy = (GstQuery *) gst_mini_object_new (GST_TYPE_QUERY);
210
211   copy->type = query->type;
212
213   if (query->structure) {
214     copy->structure = gst_structure_copy (query->structure);
215     gst_structure_set_parent_refcount (copy->structure,
216         &query->mini_object.refcount);
217   }
218
219   return copy;
220 }
221
222
223
224 /**
225  * gst_query_type_register:
226  * @nick: The nick of the new query
227  * @description: The description of the new query
228  *
229  * Create a new GstQueryType based on the nick or return an
230  * already registered query with that nick
231  *
232  * Returns: A new GstQueryType or an already registered query
233  * with the same nick.
234  */
235 GstQueryType
236 gst_query_type_register (const gchar * nick, const gchar * description)
237 {
238   GstQueryTypeDefinition *query;
239   GstQueryType lookup;
240
241   g_return_val_if_fail (nick != NULL, GST_QUERY_NONE);
242   g_return_val_if_fail (description != NULL, GST_QUERY_NONE);
243
244   lookup = gst_query_type_get_by_nick (nick);
245   if (lookup != GST_QUERY_NONE)
246     return lookup;
247
248   query = g_slice_new (GstQueryTypeDefinition);
249   query->value = (GstQueryType) _n_values;
250   query->nick = g_strdup (nick);
251   query->description = g_strdup (description);
252   query->quark = g_quark_from_static_string (query->nick);
253
254   g_static_mutex_lock (&mutex);
255   g_hash_table_insert (_nick_to_query, (gpointer) query->nick, query);
256   g_hash_table_insert (_query_type_to_nick, GINT_TO_POINTER (query->value),
257       query);
258   _gst_queries = g_list_append (_gst_queries, query);
259   _n_values++;
260   g_static_mutex_unlock (&mutex);
261
262   return query->value;
263 }
264
265 /**
266  * gst_query_type_get_by_nick:
267  * @nick: The nick of the query
268  *
269  * Get the query type registered with @nick.
270  *
271  * Returns: The query registered with @nick or #GST_QUERY_NONE
272  * if the query was not registered.
273  */
274 GstQueryType
275 gst_query_type_get_by_nick (const gchar * nick)
276 {
277   GstQueryTypeDefinition *query;
278
279   g_return_val_if_fail (nick != NULL, GST_QUERY_NONE);
280
281   g_static_mutex_lock (&mutex);
282   query = g_hash_table_lookup (_nick_to_query, nick);
283   g_static_mutex_unlock (&mutex);
284
285   if (query != NULL)
286     return query->value;
287   else
288     return GST_QUERY_NONE;
289 }
290
291 /**
292  * gst_query_types_contains:
293  * @types: The query array to search
294  * @type: the #GstQueryType to find
295  *
296  * See if the given #GstQueryType is inside the @types query types array.
297  *
298  * Returns: TRUE if the type is found inside the array
299  */
300 gboolean
301 gst_query_types_contains (const GstQueryType * types, GstQueryType type)
302 {
303   if (!types)
304     return FALSE;
305
306   while (*types) {
307     if (*types == type)
308       return TRUE;
309
310     types++;
311   }
312   return FALSE;
313 }
314
315
316 /**
317  * gst_query_type_get_details:
318  * @type: a #GstQueryType
319  *
320  * Get details about the given #GstQueryType.
321  *
322  * Returns: The #GstQueryTypeDefinition for @type or NULL on failure.
323  */
324 const GstQueryTypeDefinition *
325 gst_query_type_get_details (GstQueryType type)
326 {
327   const GstQueryTypeDefinition *result;
328
329   g_static_mutex_lock (&mutex);
330   result = g_hash_table_lookup (_query_type_to_nick, GINT_TO_POINTER (type));
331   g_static_mutex_unlock (&mutex);
332
333   return result;
334 }
335
336 /**
337  * gst_query_type_iterate_definitions:
338  *
339  * Get a #GstIterator of all the registered query types. The definitions
340  * iterated over are read only.
341  *
342  * Free-function: gst_iterator_free
343  *
344  * Returns: (transfer full): a #GstIterator of #GstQueryTypeDefinition.
345  */
346 GstIterator *
347 gst_query_type_iterate_definitions (void)
348 {
349   GstIterator *result;
350
351   g_static_mutex_lock (&mutex);
352   /* FIXME: register a boxed type for GstQueryTypeDefinition */
353   result = gst_iterator_new_list (G_TYPE_POINTER,
354       g_static_mutex_get_mutex (&mutex), &_n_values, &_gst_queries,
355       NULL, NULL, NULL);
356   g_static_mutex_unlock (&mutex);
357
358   return result;
359 }
360
361 static GstQuery *
362 gst_query_new (GstQueryType type, GstStructure * structure)
363 {
364   GstQuery *query;
365
366   query = (GstQuery *) gst_mini_object_new (GST_TYPE_QUERY);
367
368   GST_DEBUG ("creating new query %p %s", query, gst_query_type_get_name (type));
369
370   query->type = type;
371
372   if (structure) {
373     query->structure = structure;
374     gst_structure_set_parent_refcount (query->structure,
375         &query->mini_object.refcount);
376   } else {
377     query->structure = NULL;
378   }
379
380   return query;
381 }
382
383 /**
384  * gst_query_new_position:
385  * @format: the default #GstFormat for the new query
386  *
387  * Constructs a new query stream position query object. Use gst_query_unref()
388  * when done with it. A position query is used to query the current position
389  * of playback in the streams, in some format.
390  *
391  * Free-function: gst_query_unref
392  *
393  * Returns: (transfer full): a new #GstQuery
394  */
395 GstQuery *
396 gst_query_new_position (GstFormat format)
397 {
398   GstQuery *query;
399   GstStructure *structure;
400
401   structure = gst_structure_id_new (GST_QUARK (QUERY_POSITION),
402       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
403       GST_QUARK (CURRENT), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
404
405   query = gst_query_new (GST_QUERY_POSITION, structure);
406
407   return query;
408 }
409
410 /**
411  * gst_query_set_position:
412  * @query: a #GstQuery with query type GST_QUERY_POSITION
413  * @format: the requested #GstFormat
414  * @cur: the position to set
415  *
416  * Answer a position query by setting the requested value in the given format.
417  */
418 void
419 gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur)
420 {
421   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
422
423   gst_structure_id_set (query->structure,
424       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
425       GST_QUARK (CURRENT), G_TYPE_INT64, cur, NULL);
426 }
427
428 /**
429  * gst_query_parse_position:
430  * @query: a #GstQuery
431  * @format: (out) (allow-none): the storage for the #GstFormat of the
432  *     position values (may be NULL)
433  * @cur: (out) (allow-none): the storage for the current position (may be NULL)
434  *
435  * Parse a position query, writing the format into @format, and the position
436  * into @cur, if the respective parameters are non-NULL.
437  */
438 void
439 gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
440 {
441   GstStructure *structure;
442
443   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
444
445   structure = query->structure;
446   if (format)
447     *format =
448         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
449             GST_QUARK (FORMAT)));
450   if (cur)
451     *cur = g_value_get_int64 (gst_structure_id_get_value (structure,
452             GST_QUARK (CURRENT)));
453 }
454
455
456 /**
457  * gst_query_new_duration:
458  * @format: the #GstFormat for this duration query
459  *
460  * Constructs a new stream duration query object to query in the given format.
461  * Use gst_query_unref() when done with it. A duration query will give the
462  * total length of the stream.
463  *
464  * Free-function: gst_query_unref
465  *
466  * Returns: (transfer full): a new #GstQuery
467  */
468 GstQuery *
469 gst_query_new_duration (GstFormat format)
470 {
471   GstQuery *query;
472   GstStructure *structure;
473
474   structure = gst_structure_id_new (GST_QUARK (QUERY_DURATION),
475       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
476       GST_QUARK (DURATION), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
477
478   query = gst_query_new (GST_QUERY_DURATION, structure);
479
480   return query;
481 }
482
483 /**
484  * gst_query_set_duration:
485  * @query: a #GstQuery
486  * @format: the #GstFormat for the duration
487  * @duration: the duration of the stream
488  *
489  * Answer a duration query by setting the requested value in the given format.
490  */
491 void
492 gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration)
493 {
494   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
495
496   gst_structure_id_set (query->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 = query->structure;
520   if (format)
521     *format =
522         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
523             GST_QUARK (FORMAT)));
524   if (duration)
525     *duration = g_value_get_int64 (gst_structure_id_get_value (structure,
526             GST_QUARK (DURATION)));
527 }
528
529 /**
530  * gst_query_new_latency:
531  *
532  * Constructs a new latency query object.
533  * Use gst_query_unref() when done with it. A latency query is usually performed
534  * by sinks to compensate for additional latency introduced by elements in the
535  * pipeline.
536  *
537  * Free-function: gst_query_unref
538  *
539  * Returns: (transfer full): a #GstQuery
540  *
541  * Since: 0.10.12
542  */
543 GstQuery *
544 gst_query_new_latency (void)
545 {
546   GstQuery *query;
547   GstStructure *structure;
548
549   structure = gst_structure_id_new (GST_QUARK (QUERY_LATENCY),
550       GST_QUARK (LIVE), G_TYPE_BOOLEAN, FALSE,
551       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
552       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (-1), NULL);
553
554   query = gst_query_new (GST_QUERY_LATENCY, structure);
555
556   return query;
557 }
558
559 /**
560  * gst_query_set_latency:
561  * @query: a #GstQuery
562  * @live: if there is a live element upstream
563  * @min_latency: the minimal latency of the live element
564  * @max_latency: the maximal latency of the live element
565  *
566  * Answer a latency query by setting the requested values in the given format.
567  *
568  * Since: 0.10.12
569  */
570 void
571 gst_query_set_latency (GstQuery * query, gboolean live,
572     GstClockTime min_latency, GstClockTime max_latency)
573 {
574   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
575
576   gst_structure_id_set (query->structure,
577       GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
578       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, min_latency,
579       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, max_latency, NULL);
580 }
581
582 /**
583  * gst_query_parse_latency:
584  * @query: a #GstQuery
585  * @live: (out) (allow-none): storage for live or NULL
586  * @min_latency: (out) (allow-none): the storage for the min latency or NULL
587  * @max_latency: (out) (allow-none): the storage for the max latency or NULL
588  *
589  * Parse a latency query answer.
590  *
591  * Since: 0.10.12
592  */
593 void
594 gst_query_parse_latency (GstQuery * query, gboolean * live,
595     GstClockTime * min_latency, GstClockTime * max_latency)
596 {
597   GstStructure *structure;
598
599   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
600
601   structure = query->structure;
602   if (live)
603     *live =
604         g_value_get_boolean (gst_structure_id_get_value (structure,
605             GST_QUARK (LIVE)));
606   if (min_latency)
607     *min_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
608             GST_QUARK (MIN_LATENCY)));
609   if (max_latency)
610     *max_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
611             GST_QUARK (MAX_LATENCY)));
612 }
613
614 /**
615  * gst_query_new_convert:
616  * @src_format: the source #GstFormat for the new query
617  * @value: the value to convert
618  * @dest_format: the target #GstFormat
619  *
620  * Constructs a new convert query object. Use gst_query_unref()
621  * when done with it. A convert query is used to ask for a conversion between
622  * one format and another.
623  *
624  * Free-function: gst_query_unref
625  *
626  * Returns: (transfer full): a #GstQuery
627  */
628 GstQuery *
629 gst_query_new_convert (GstFormat src_format, gint64 value,
630     GstFormat dest_format)
631 {
632   GstQuery *query;
633   GstStructure *structure;
634
635   structure = gst_structure_id_new (GST_QUARK (QUERY_CONVERT),
636       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
637       GST_QUARK (SRC_VALUE), G_TYPE_INT64, value,
638       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
639       GST_QUARK (DEST_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
640
641   query = gst_query_new (GST_QUERY_CONVERT, structure);
642
643   return query;
644 }
645
646 /**
647  * gst_query_set_convert:
648  * @query: a #GstQuery
649  * @src_format: the source #GstFormat
650  * @src_value: the source value
651  * @dest_format: the destination #GstFormat
652  * @dest_value: the destination value
653  *
654  * Answer a convert query by setting the requested values.
655  */
656 void
657 gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value,
658     GstFormat dest_format, gint64 dest_value)
659 {
660   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
661
662   gst_structure_id_set (query->structure,
663       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
664       GST_QUARK (SRC_VALUE), G_TYPE_INT64, src_value,
665       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
666       GST_QUARK (DEST_VALUE), G_TYPE_INT64, dest_value, NULL);
667 }
668
669 /**
670  * gst_query_parse_convert:
671  * @query: a #GstQuery
672  * @src_format: (out) (allow-none): the storage for the #GstFormat of the
673  *     source value, or NULL
674  * @src_value: (out) (allow-none): the storage for the source value, or NULL
675  * @dest_format: (out) (allow-none): the storage for the #GstFormat of the
676  *     destination value, or NULL
677  * @dest_value: (out) (allow-none): the storage for the destination value,
678  *     or NULL
679  *
680  * Parse a convert query answer. Any of @src_format, @src_value, @dest_format,
681  * and @dest_value may be NULL, in which case that value is omitted.
682  */
683 void
684 gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
685     gint64 * src_value, GstFormat * dest_format, gint64 * dest_value)
686 {
687   GstStructure *structure;
688
689   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
690
691   structure = query->structure;
692   if (src_format)
693     *src_format =
694         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
695             GST_QUARK (SRC_FORMAT)));
696   if (src_value)
697     *src_value = g_value_get_int64 (gst_structure_id_get_value (structure,
698             GST_QUARK (SRC_VALUE)));
699   if (dest_format)
700     *dest_format =
701         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
702             GST_QUARK (DEST_FORMAT)));
703   if (dest_value)
704     *dest_value = g_value_get_int64 (gst_structure_id_get_value (structure,
705             GST_QUARK (DEST_VALUE)));
706 }
707
708 /**
709  * gst_query_new_segment:
710  * @format: the #GstFormat for the new query
711  *
712  * Constructs a new segment query object. Use gst_query_unref()
713  * when done with it. A segment query is used to discover information about the
714  * currently configured segment for playback.
715  *
716  * Free-function: gst_query_unref
717  *
718  * Returns: (transfer full): a new #GstQuery
719  */
720 GstQuery *
721 gst_query_new_segment (GstFormat format)
722 {
723   GstQuery *query;
724   GstStructure *structure;
725
726   structure = gst_structure_id_new (GST_QUARK (QUERY_SEGMENT),
727       GST_QUARK (RATE), G_TYPE_DOUBLE, (gdouble) 0.0,
728       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
729       GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
730       GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
731
732   query = gst_query_new (GST_QUERY_SEGMENT, structure);
733
734   return query;
735 }
736
737 /**
738  * gst_query_set_segment:
739  * @query: a #GstQuery
740  * @rate: the rate of the segment
741  * @format: the #GstFormat of the segment values (@start_value and @stop_value)
742  * @start_value: the start value
743  * @stop_value: the stop value
744  *
745  * Answer a segment query by setting the requested values. The normal
746  * playback segment of a pipeline is 0 to duration at the default rate of
747  * 1.0. If a seek was performed on the pipeline to play a different
748  * segment, this query will return the range specified in the last seek.
749  *
750  * @start_value and @stop_value will respectively contain the configured
751  * playback range start and stop values expressed in @format.
752  * The values are always between 0 and the duration of the media and
753  * @start_value <= @stop_value. @rate will contain the playback rate. For
754  * negative rates, playback will actually happen from @stop_value to
755  * @start_value.
756  */
757 void
758 gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format,
759     gint64 start_value, gint64 stop_value)
760 {
761   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
762
763   gst_structure_id_set (query->structure,
764       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
765       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
766       GST_QUARK (START_VALUE), G_TYPE_INT64, start_value,
767       GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop_value, NULL);
768 }
769
770 /**
771  * gst_query_parse_segment:
772  * @query: a #GstQuery
773  * @rate: (out) (allow-none): the storage for the rate of the segment, or NULL
774  * @format: (out) (allow-none): the storage for the #GstFormat of the values,
775  *     or NULL
776  * @start_value: (out) (allow-none): the storage for the start value, or NULL
777  * @stop_value: (out) (allow-none): the storage for the stop value, or NULL
778  *
779  * Parse a segment query answer. Any of @rate, @format, @start_value, and
780  * @stop_value may be NULL, which will cause this value to be omitted.
781  *
782  * See gst_query_set_segment() for an explanation of the function arguments.
783  */
784 void
785 gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
786     gint64 * start_value, gint64 * stop_value)
787 {
788   GstStructure *structure;
789
790   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
791
792   structure = query->structure;
793   if (rate)
794     *rate = g_value_get_double (gst_structure_id_get_value (structure,
795             GST_QUARK (RATE)));
796   if (format)
797     *format =
798         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
799             GST_QUARK (FORMAT)));
800   if (start_value)
801     *start_value = g_value_get_int64 (gst_structure_id_get_value (structure,
802             GST_QUARK (START_VALUE)));
803   if (stop_value)
804     *stop_value = g_value_get_int64 (gst_structure_id_get_value (structure,
805             GST_QUARK (STOP_VALUE)));
806 }
807
808 /**
809  * gst_query_new_application:
810  * @type: the query type
811  * @structure: a structure for the query
812  *
813  * Constructs a new custom application query object. Use gst_query_unref()
814  * when done with it.
815  *
816  * Free-function: gst_query_unref
817  *
818  * Returns: (transfer full): a new #GstQuery
819  */
820 GstQuery *
821 gst_query_new_application (GstQueryType type, GstStructure * structure)
822 {
823   g_return_val_if_fail (gst_query_type_get_details (type) != NULL, NULL);
824   g_return_val_if_fail (structure != NULL, NULL);
825
826   return gst_query_new (type, structure);
827 }
828
829 /**
830  * gst_query_get_structure:
831  * @query: a #GstQuery
832  *
833  * Get the structure of a query.
834  *
835  * Returns: (transfer none): the #GstStructure of the query. The structure is
836  *     still owned by the query and will therefore be freed when the query
837  *     is unreffed.
838  */
839 GstStructure *
840 gst_query_get_structure (GstQuery * query)
841 {
842   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
843
844   return query->structure;
845 }
846
847 /**
848  * gst_query_new_seeking:
849  * @format: the default #GstFormat for the new query
850  *
851  * Constructs a new query object for querying seeking properties of
852  * the stream.
853  *
854  * Free-function: gst_query_unref
855  *
856  * Returns: (transfer full): a new #GstQuery
857  */
858 GstQuery *
859 gst_query_new_seeking (GstFormat format)
860 {
861   GstQuery *query;
862   GstStructure *structure;
863
864   structure = gst_structure_id_new (GST_QUARK (QUERY_SEEKING),
865       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
866       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, FALSE,
867       GST_QUARK (SEGMENT_START), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
868       GST_QUARK (SEGMENT_END), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
869
870   query = gst_query_new (GST_QUERY_SEEKING, structure);
871
872   return query;
873 }
874
875 /**
876  * gst_query_set_seeking:
877  * @query: a #GstQuery
878  * @format: the format to set for the @segment_start and @segment_end values
879  * @seekable: the seekable flag to set
880  * @segment_start: the segment_start to set
881  * @segment_end: the segment_end to set
882  *
883  * Set the seeking query result fields in @query.
884  */
885 void
886 gst_query_set_seeking (GstQuery * query, GstFormat format,
887     gboolean seekable, gint64 segment_start, gint64 segment_end)
888 {
889   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
890
891   gst_structure_id_set (query->structure,
892       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
893       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable,
894       GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start,
895       GST_QUARK (SEGMENT_END), G_TYPE_INT64, segment_end, NULL);
896 }
897
898 /**
899  * gst_query_parse_seeking:
900  * @query: a GST_QUERY_SEEKING type query #GstQuery
901  * @format: (out) (allow-none): the format to set for the @segment_start
902  *     and @segment_end values, or NULL
903  * @seekable: (out) (allow-none): the seekable flag to set, or NULL
904  * @segment_start: (out) (allow-none): the segment_start to set, or NULL
905  * @segment_end: (out) (allow-none): the segment_end to set, or NULL
906  *
907  * Parse a seeking query, writing the format into @format, and
908  * other results into the passed parameters, if the respective parameters
909  * are non-NULL
910  */
911 void
912 gst_query_parse_seeking (GstQuery * query, GstFormat * format,
913     gboolean * seekable, gint64 * segment_start, gint64 * segment_end)
914 {
915   GstStructure *structure;
916
917   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
918
919   structure = query->structure;
920   if (format)
921     *format =
922         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
923             GST_QUARK (FORMAT)));
924   if (seekable)
925     *seekable = g_value_get_boolean (gst_structure_id_get_value (structure,
926             GST_QUARK (SEEKABLE)));
927   if (segment_start)
928     *segment_start = g_value_get_int64 (gst_structure_id_get_value (structure,
929             GST_QUARK (SEGMENT_START)));
930   if (segment_end)
931     *segment_end = g_value_get_int64 (gst_structure_id_get_value (structure,
932             GST_QUARK (SEGMENT_END)));
933 }
934
935 /**
936  * gst_query_new_formats:
937  *
938  * Constructs a new query object for querying formats of
939  * the stream.
940  *
941  * Free-function: gst_query_unref
942  *
943  * Returns: (transfer full): a new #GstQuery
944  *
945  * Since: 0.10.4
946  */
947 GstQuery *
948 gst_query_new_formats (void)
949 {
950   GstQuery *query;
951   GstStructure *structure;
952
953   structure = gst_structure_id_empty_new (GST_QUARK (QUERY_FORMATS));
954   query = gst_query_new (GST_QUERY_FORMATS, structure);
955
956   return query;
957 }
958
959 static void
960 gst_query_list_add_format (GValue * list, GstFormat format)
961 {
962   GValue item = { 0, };
963
964   g_value_init (&item, GST_TYPE_FORMAT);
965   g_value_set_enum (&item, format);
966   gst_value_list_append_value (list, &item);
967   g_value_unset (&item);
968 }
969
970 /**
971  * gst_query_set_formats:
972  * @query: a #GstQuery
973  * @n_formats: the number of formats to set.
974  * @...: A number of @GstFormats equal to @n_formats.
975  *
976  * Set the formats query result fields in @query. The number of formats passed
977  * must be equal to @n_formats.
978  */
979 void
980 gst_query_set_formats (GstQuery * query, gint n_formats, ...)
981 {
982   va_list ap;
983   GValue list = { 0, };
984   gint i;
985
986   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
987
988   g_value_init (&list, GST_TYPE_LIST);
989
990   va_start (ap, n_formats);
991   for (i = 0; i < n_formats; i++) {
992     gst_query_list_add_format (&list, va_arg (ap, GstFormat));
993   }
994   va_end (ap);
995
996   gst_structure_set_value (query->structure, "formats", &list);
997
998   g_value_unset (&list);
999
1000 }
1001
1002 /**
1003  * gst_query_set_formatsv:
1004  * @query: a #GstQuery
1005  * @n_formats: the number of formats to set.
1006  * @formats: (in) (array length=n_formats): an array containing @n_formats
1007  *     @GstFormat values.
1008  *
1009  * Set the formats query result fields in @query. The number of formats passed
1010  * in the @formats array must be equal to @n_formats.
1011  *
1012  * Since: 0.10.4
1013  */
1014 void
1015 gst_query_set_formatsv (GstQuery * query, gint n_formats,
1016     const GstFormat * formats)
1017 {
1018   GValue list = { 0, };
1019   gint i;
1020
1021   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
1022
1023   g_value_init (&list, GST_TYPE_LIST);
1024   for (i = 0; i < n_formats; i++) {
1025     gst_query_list_add_format (&list, formats[i]);
1026   }
1027   gst_structure_set_value (query->structure, "formats", &list);
1028
1029   g_value_unset (&list);
1030 }
1031
1032 /**
1033  * gst_query_parse_formats_length:
1034  * @query: a #GstQuery
1035  * @n_formats: (out): the number of formats in this query.
1036  *
1037  * Parse the number of formats in the formats @query.
1038  *
1039  * Since: 0.10.4
1040  */
1041 void
1042 gst_query_parse_formats_length (GstQuery * query, guint * n_formats)
1043 {
1044   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
1045
1046   if (n_formats) {
1047     const GValue *list;
1048
1049     list = gst_structure_get_value (query->structure, "formats");
1050     if (list == NULL)
1051       *n_formats = 0;
1052     else
1053       *n_formats = gst_value_list_get_size (list);
1054   }
1055 }
1056
1057 /**
1058  * gst_query_parse_formats_nth:
1059  * @query: a #GstQuery
1060  * @nth: (out): the nth format to retrieve.
1061  * @format: (out): a pointer to store the nth format
1062  *
1063  * Parse the format query and retrieve the @nth format from it into
1064  * @format. If the list contains less elements than @nth, @format will be
1065  * set to GST_FORMAT_UNDEFINED.
1066  *
1067  * Since: 0.10.4
1068  */
1069 void
1070 gst_query_parse_formats_nth (GstQuery * query, guint nth, GstFormat * format)
1071 {
1072   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
1073
1074   if (format) {
1075     const GValue *list;
1076
1077     list = gst_structure_get_value (query->structure, "formats");
1078     if (list == NULL) {
1079       *format = GST_FORMAT_UNDEFINED;
1080     } else {
1081       if (nth < gst_value_list_get_size (list)) {
1082         *format =
1083             (GstFormat) g_value_get_enum (gst_value_list_get_value (list, nth));
1084       } else
1085         *format = GST_FORMAT_UNDEFINED;
1086     }
1087   }
1088 }
1089
1090 /**
1091  * gst_query_new_buffering
1092  * @format: the default #GstFormat for the new query
1093  *
1094  * Constructs a new query object for querying the buffering status of
1095  * a stream.
1096  *
1097  * Free-function: gst_query_new
1098  *
1099  * Returns: (transfer full): a new #GstQuery
1100  *
1101  * Since: 0.10.20
1102  */
1103 GstQuery *
1104 gst_query_new_buffering (GstFormat format)
1105 {
1106   GstQuery *query;
1107   GstStructure *structure;
1108
1109   /* by default, we configure the answer as no buffering with a 100% buffering
1110    * progress */
1111   structure = gst_structure_id_new (GST_QUARK (QUERY_BUFFERING),
1112       GST_QUARK (BUSY), G_TYPE_BOOLEAN, FALSE,
1113       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, 100,
1114       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
1115       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
1116       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
1117       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, G_GINT64_CONSTANT (0),
1118       GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
1119       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1120       GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
1121       GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
1122
1123   query = gst_query_new (GST_QUERY_BUFFERING, structure);
1124
1125   return query;
1126 }
1127
1128 /**
1129  * gst_query_set_buffering_percent
1130  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1131  * @busy: if buffering is busy
1132  * @percent: a buffering percent
1133  *
1134  * Set the percentage of buffered data. This is a value between 0 and 100.
1135  * The @busy indicator is %TRUE when the buffering is in progress.
1136  *
1137  * Since: 0.10.20
1138  */
1139 void
1140 gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent)
1141 {
1142   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1143   g_return_if_fail (percent >= 0 && percent <= 100);
1144
1145   gst_structure_id_set (query->structure,
1146       GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy,
1147       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL);
1148 }
1149
1150 /**
1151  * gst_query_parse_buffering_percent
1152  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1153  * @busy: (out) (allow-none): if buffering is busy, or NULL
1154  * @percent: (out) (allow-none): a buffering percent, or NULL
1155  *
1156  * Get the percentage of buffered data. This is a value between 0 and 100.
1157  * The @busy indicator is %TRUE when the buffering is in progress.
1158  *
1159  * Since: 0.10.20
1160  */
1161 void
1162 gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy,
1163     gint * percent)
1164 {
1165   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1166
1167   if (busy)
1168     *busy = g_value_get_boolean (gst_structure_id_get_value (query->structure,
1169             GST_QUARK (BUSY)));
1170   if (percent)
1171     *percent = g_value_get_int (gst_structure_id_get_value (query->structure,
1172             GST_QUARK (BUFFER_PERCENT)));
1173 }
1174
1175 /**
1176  * gst_query_set_buffering_stats:
1177  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1178  * @mode: a buffering mode
1179  * @avg_in: the average input rate
1180  * @avg_out: the average output rate
1181  * @buffering_left: amount of buffering time left
1182  *
1183  * Configures the buffering stats values in @query.
1184  *
1185  * Since: 0.10.20
1186  */
1187 void
1188 gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode,
1189     gint avg_in, gint avg_out, gint64 buffering_left)
1190 {
1191   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1192
1193   gst_structure_id_set (query->structure,
1194       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
1195       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
1196       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
1197       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
1198 }
1199
1200 /**
1201  * gst_query_parse_buffering_stats:
1202  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1203  * @mode: (out) (allow-none): a buffering mode, or NULL
1204  * @avg_in: (out) (allow-none): the average input rate, or NULL
1205  * @avg_out: (out) (allow-none): the average output rat, or NULLe
1206  * @buffering_left: (out) (allow-none): amount of buffering time left, or NULL
1207  *
1208  * Extracts the buffering stats values from @query.
1209  *
1210  * Since: 0.10.20
1211  */
1212 void
1213 gst_query_parse_buffering_stats (GstQuery * query,
1214     GstBufferingMode * mode, gint * avg_in, gint * avg_out,
1215     gint64 * buffering_left)
1216 {
1217   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1218
1219   if (mode)
1220     *mode = (GstBufferingMode)
1221         g_value_get_enum (gst_structure_id_get_value (query->structure,
1222             GST_QUARK (BUFFERING_MODE)));
1223   if (avg_in)
1224     *avg_in = g_value_get_int (gst_structure_id_get_value (query->structure,
1225             GST_QUARK (AVG_IN_RATE)));
1226   if (avg_out)
1227     *avg_out = g_value_get_int (gst_structure_id_get_value (query->structure,
1228             GST_QUARK (AVG_OUT_RATE)));
1229   if (buffering_left)
1230     *buffering_left =
1231         g_value_get_int64 (gst_structure_id_get_value (query->structure,
1232             GST_QUARK (BUFFERING_LEFT)));
1233 }
1234
1235
1236 /**
1237  * gst_query_set_buffering_range:
1238  * @query: a #GstQuery
1239  * @format: the format to set for the @start and @stop values
1240  * @start: the start to set
1241  * @stop: the stop to set
1242  * @estimated_total: estimated total amount of download time
1243  *
1244  * Set the available query result fields in @query.
1245  *
1246  * Since: 0.10.20
1247  */
1248 void
1249 gst_query_set_buffering_range (GstQuery * query, GstFormat format,
1250     gint64 start, gint64 stop, gint64 estimated_total)
1251 {
1252   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1253
1254   gst_structure_id_set (query->structure,
1255       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1256       GST_QUARK (START_VALUE), G_TYPE_INT64, start,
1257       GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop,
1258       GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, estimated_total, NULL);
1259 }
1260
1261 /**
1262  * gst_query_parse_buffering_range:
1263  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1264  * @format: (out) (allow-none): the format to set for the @segment_start
1265  *     and @segment_end values, or NULL
1266  * @start: (out) (allow-none): the start to set, or NULL
1267  * @stop: (out) (allow-none): the stop to set, or NULL
1268  * @estimated_total: (out) (allow-none): estimated total amount of download
1269  *     time, or NULL
1270  *
1271  * Parse an available query, writing the format into @format, and
1272  * other results into the passed parameters, if the respective parameters
1273  * are non-NULL
1274  *
1275  * Since: 0.10.20
1276  */
1277 void
1278 gst_query_parse_buffering_range (GstQuery * query, GstFormat * format,
1279     gint64 * start, gint64 * stop, gint64 * estimated_total)
1280 {
1281   GstStructure *structure;
1282
1283   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1284
1285   structure = query->structure;
1286   if (format)
1287     *format =
1288         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
1289             GST_QUARK (FORMAT)));
1290   if (start)
1291     *start = g_value_get_int64 (gst_structure_id_get_value (structure,
1292             GST_QUARK (START_VALUE)));
1293   if (stop)
1294     *stop = g_value_get_int64 (gst_structure_id_get_value (structure,
1295             GST_QUARK (STOP_VALUE)));
1296   if (estimated_total)
1297     *estimated_total =
1298         g_value_get_int64 (gst_structure_id_get_value (structure,
1299             GST_QUARK (ESTIMATED_TOTAL)));
1300 }
1301
1302 /**
1303  * gst_query_add_buffering_range
1304  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1305  * @start: start position of the range
1306  * @stop: stop position of the range
1307  *
1308  * Set the buffering-ranges array field in @query. The current last
1309  * start position of the array should be inferior to @start.
1310  *
1311  * Returns: a #gboolean indicating if the range was added or not.
1312  *
1313  * Since: 0.10.31
1314  */
1315 gboolean
1316 gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop)
1317 {
1318   GValueArray *array;
1319   GValue *last_array_value;
1320   const GValue *value;
1321   GValue range_value = { 0 };
1322
1323   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE);
1324
1325   if (G_UNLIKELY (start >= stop))
1326     return FALSE;
1327
1328   value =
1329       gst_structure_id_get_value (query->structure,
1330       GST_QUARK (BUFFERING_RANGES));
1331   if (value) {
1332     array = (GValueArray *) g_value_get_boxed (value);
1333     last_array_value = g_value_array_get_nth (array, array->n_values - 1);
1334     if (G_UNLIKELY (start <= gst_value_get_int64_range_min (last_array_value)))
1335       return FALSE;
1336   } else {
1337     GValue new_array_val = { 0, };
1338
1339     array = g_value_array_new (0);
1340
1341     g_value_init (&new_array_val, G_TYPE_VALUE_ARRAY);
1342     g_value_take_boxed (&new_array_val, array);
1343
1344     /* set the value array only once, so we then modify (append to) the
1345      * existing value array owned by the GstStructure / the field's GValue */
1346     gst_structure_id_take_value (query->structure, GST_QUARK (BUFFERING_RANGES),
1347         &new_array_val);
1348   }
1349
1350   g_value_init (&range_value, GST_TYPE_INT64_RANGE);
1351   gst_value_set_int64_range (&range_value, start, stop);
1352   g_value_array_append (array, &range_value);
1353   /* skip the g_value_unset(&range_value) here, we know it's not needed */
1354
1355   return TRUE;
1356 }
1357
1358 /**
1359  * gst_query_get_n_buffering_ranges
1360  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1361  *
1362  * Retrieve the number of values currently stored in the
1363  * buffered-ranges array of the query's structure.
1364  *
1365  * Returns: the range array size as a #guint.
1366  *
1367  * Since: 0.10.31
1368  */
1369 guint
1370 gst_query_get_n_buffering_ranges (GstQuery * query)
1371 {
1372   GValueArray *array;
1373   const GValue *value;
1374   guint size = 0;
1375
1376   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, 0);
1377
1378   value =
1379       gst_structure_id_get_value (query->structure,
1380       GST_QUARK (BUFFERING_RANGES));
1381   if (value) {
1382     array = (GValueArray *) g_value_get_boxed (value);
1383     size = array->n_values;
1384   }
1385   return size;
1386 }
1387
1388
1389 /**
1390  * gst_query_parse_nth_buffering_range
1391  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1392  * @index: position in the buffered-ranges array to read
1393  * @start: (out) (allow-none): the start position to set, or NULL
1394  * @stop: (out) (allow-none): the stop position to set, or NULL
1395  *
1396  * Parse an available query and get the start and stop values stored
1397  * at the @index of the buffered ranges array.
1398  *
1399  * Returns: a #gboolean indicating if the parsing succeeded.
1400  *
1401  * Since: 0.10.31
1402  */
1403 gboolean
1404 gst_query_parse_nth_buffering_range (GstQuery * query, guint index,
1405     gint64 * start, gint64 * stop)
1406 {
1407   const GValue *value;
1408   GValueArray *ranges;
1409   GValue *range_value;
1410   gboolean ret = FALSE;
1411
1412   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, ret);
1413
1414   value =
1415       gst_structure_id_get_value (query->structure,
1416       GST_QUARK (BUFFERING_RANGES));
1417   ranges = (GValueArray *) g_value_get_boxed (value);
1418   range_value = g_value_array_get_nth (ranges, index);
1419   if (range_value) {
1420     if (start)
1421       *start = gst_value_get_int64_range_min (range_value);
1422     if (stop)
1423       *stop = gst_value_get_int64_range_max (range_value);
1424     ret = TRUE;
1425   }
1426
1427   return ret;
1428 }
1429
1430
1431 /**
1432  * gst_query_new_uri:
1433  *
1434  * Constructs a new query URI query object. Use gst_query_unref()
1435  * when done with it. An URI query is used to query the current URI
1436  * that is used by the source or sink.
1437  *
1438  * Free-function: gst_query_unref
1439  *
1440  * Returns: (transfer full): a new #GstQuery
1441  *
1442  * Since: 0.10.22
1443  */
1444 GstQuery *
1445 gst_query_new_uri (void)
1446 {
1447   GstQuery *query;
1448   GstStructure *structure;
1449
1450   structure = gst_structure_id_new (GST_QUARK (QUERY_URI),
1451       GST_QUARK (URI), G_TYPE_STRING, NULL, NULL);
1452
1453   query = gst_query_new (GST_QUERY_URI, structure);
1454
1455   return query;
1456 }
1457
1458 /**
1459  * gst_query_set_uri:
1460  * @query: a #GstQuery with query type GST_QUERY_URI
1461  * @uri: the URI to set
1462  *
1463  * Answer a URI query by setting the requested URI.
1464  *
1465  * Since: 0.10.22
1466  */
1467 void
1468 gst_query_set_uri (GstQuery * query, const gchar * uri)
1469 {
1470   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1471   g_return_if_fail (gst_uri_is_valid (uri));
1472
1473   gst_structure_id_set (query->structure, GST_QUARK (URI), G_TYPE_STRING, uri,
1474       NULL);
1475 }
1476
1477 /**
1478  * gst_query_parse_uri:
1479  * @query: a #GstQuery
1480  * @uri: (out callee-allocates) (allow-none): the storage for the current URI
1481  *     (may be NULL)
1482  *
1483  * Parse an URI query, writing the URI into @uri as a newly
1484  * allocated string, if the respective parameters are non-NULL.
1485  * Free the string with g_free() after usage.
1486  *
1487  * Since: 0.10.22
1488  */
1489 void
1490 gst_query_parse_uri (GstQuery * query, gchar ** uri)
1491 {
1492   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1493
1494   if (uri)
1495     *uri = g_value_dup_string (gst_structure_id_get_value (query->structure,
1496             GST_QUARK (URI)));
1497 }