query: add gst_clear_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., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 /**
25  * SECTION:gstquery
26  * @title: GstQuery
27  * @short_description: Provide functions to create queries, and to set and parse
28  *                     values in them.
29  * @see_also: #GstPad, #GstElement
30  *
31  * Queries can be performed on pads (gst_pad_query()) and elements
32  * (gst_element_query()). Please note that some queries might need a running
33  * pipeline to work.
34  *
35  * Queries can be created using the gst_query_new_*() functions.
36  * Query values can be set using gst_query_set_*(), and parsed using
37  * gst_query_parse_*() helpers.
38  *
39  * The following example shows how to query the duration of a pipeline:
40  * |[<!-- language="C" -->
41  *   GstQuery *query;
42  *   gboolean res;
43  *   query = gst_query_new_duration (GST_FORMAT_TIME);
44  *   res = gst_element_query (pipeline, query);
45  *   if (res) {
46  *     gint64 duration;
47  *     gst_query_parse_duration (query, NULL, &amp;duration);
48  *     g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration));
49  *   } else {
50  *     g_print ("duration query failed...");
51  *   }
52  *   gst_query_unref (query);
53  * ]|
54  */
55
56
57 #include "gst_private.h"
58 #include "gstinfo.h"
59 #include "gstquery.h"
60 #include "gstvalue.h"
61 #include "gstenumtypes.h"
62 #include "gstquark.h"
63 #include "gsturi.h"
64 #include "gstbufferpool.h"
65
66 GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
67 #define GST_CAT_DEFAULT gst_query_debug
68
69 GType _gst_query_type = 0;
70
71 typedef struct
72 {
73   GstQuery query;
74
75   GstStructure *structure;
76 } GstQueryImpl;
77
78 #define GST_QUERY_STRUCTURE(q)  (((GstQueryImpl *)(q))->structure)
79
80
81 typedef struct
82 {
83   const gint type;
84   const gchar *name;
85   GQuark quark;
86 } GstQueryQuarks;
87
88 static GstQueryQuarks query_quarks[] = {
89   {GST_QUERY_UNKNOWN, "unknown", 0},
90   {GST_QUERY_POSITION, "position", 0},
91   {GST_QUERY_DURATION, "duration", 0},
92   {GST_QUERY_LATENCY, "latency", 0},
93   {GST_QUERY_JITTER, "jitter", 0},
94   {GST_QUERY_RATE, "rate", 0},
95   {GST_QUERY_SEEKING, "seeking", 0},
96   {GST_QUERY_SEGMENT, "segment", 0},
97   {GST_QUERY_CONVERT, "convert", 0},
98   {GST_QUERY_FORMATS, "formats", 0},
99   {GST_QUERY_BUFFERING, "buffering", 0},
100   {GST_QUERY_CUSTOM, "custom", 0},
101   {GST_QUERY_URI, "uri", 0},
102   {GST_QUERY_ALLOCATION, "allocation", 0},
103   {GST_QUERY_SCHEDULING, "scheduling", 0},
104   {GST_QUERY_ACCEPT_CAPS, "accept-caps", 0},
105   {GST_QUERY_CAPS, "caps", 0},
106   {GST_QUERY_DRAIN, "drain", 0},
107   {GST_QUERY_CONTEXT, "context", 0},
108
109   {0, NULL, 0}
110 };
111
112 GST_DEFINE_MINI_OBJECT_TYPE (GstQuery, gst_query);
113
114 void
115 _priv_gst_query_initialize (void)
116 {
117   gint i;
118
119   _gst_query_type = gst_query_get_type ();
120
121   GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system");
122
123   for (i = 0; query_quarks[i].name; i++) {
124     query_quarks[i].quark = g_quark_from_static_string (query_quarks[i].name);
125   }
126 }
127
128 /**
129  * gst_query_type_get_name:
130  * @type: the query type
131  *
132  * Get a printable name for the given query type. Do not modify or free.
133  *
134  * Returns: a reference to the static name of the query.
135  */
136 const gchar *
137 gst_query_type_get_name (GstQueryType type)
138 {
139   gint i;
140
141   for (i = 0; query_quarks[i].name; i++) {
142     if (type == query_quarks[i].type)
143       return query_quarks[i].name;
144   }
145   return "unknown";
146 }
147
148 /**
149  * gst_query_type_to_quark:
150  * @type: the query type
151  *
152  * Get the unique quark for the given query type.
153  *
154  * Returns: the quark associated with the query type
155  */
156 GQuark
157 gst_query_type_to_quark (GstQueryType type)
158 {
159   gint i;
160
161   for (i = 0; query_quarks[i].name; i++) {
162     if (type == query_quarks[i].type)
163       return query_quarks[i].quark;
164   }
165   return 0;
166 }
167
168 /**
169  * gst_query_type_get_flags:
170  * @type: a #GstQueryType
171  *
172  * Gets the #GstQueryTypeFlags associated with @type.
173  *
174  * Returns: a #GstQueryTypeFlags.
175  */
176 GstQueryTypeFlags
177 gst_query_type_get_flags (GstQueryType type)
178 {
179   GstQueryTypeFlags ret;
180
181   ret = type & ((1 << GST_QUERY_NUM_SHIFT) - 1);
182
183   return ret;
184 }
185
186 static void
187 _gst_query_free (GstQuery * query)
188 {
189   GstStructure *s;
190
191   g_return_if_fail (query != NULL);
192
193   s = GST_QUERY_STRUCTURE (query);
194   if (s) {
195     gst_structure_set_parent_refcount (s, NULL);
196     gst_structure_free (s);
197   }
198 #ifdef USE_POISONING
199   memset (query, 0xff, sizeof (GstQueryImpl));
200 #endif
201
202   g_slice_free1 (sizeof (GstQueryImpl), query);
203 }
204
205 static GstQuery *
206 _gst_query_copy (GstQuery * query)
207 {
208   GstQuery *copy;
209   GstStructure *s;
210
211   s = GST_QUERY_STRUCTURE (query);
212   if (s) {
213     s = gst_structure_copy (s);
214   }
215   copy = gst_query_new_custom (query->type, s);
216
217   return copy;
218 }
219
220 /**
221  * gst_query_new_position:
222  * @format: the default #GstFormat for the new query
223  *
224  * Constructs a new query stream position query object. Use gst_query_unref()
225  * when done with it. A position query is used to query the current position
226  * of playback in the streams, in some format.
227  *
228  * Free-function: gst_query_unref()
229  *
230  * Returns: (transfer full): a new #GstQuery
231  */
232 GstQuery *
233 gst_query_new_position (GstFormat format)
234 {
235   GstQuery *query;
236   GstStructure *structure;
237
238   structure = gst_structure_new_id (GST_QUARK (QUERY_POSITION),
239       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
240       GST_QUARK (CURRENT), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
241
242   query = gst_query_new_custom (GST_QUERY_POSITION, structure);
243
244   return query;
245 }
246
247 /**
248  * gst_query_set_position:
249  * @query: a #GstQuery with query type GST_QUERY_POSITION
250  * @format: the requested #GstFormat
251  * @cur: the position to set
252  *
253  * Answer a position query by setting the requested value in the given format.
254  */
255 void
256 gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur)
257 {
258   GstStructure *s;
259
260   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
261
262   s = GST_QUERY_STRUCTURE (query);
263   g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s,
264               GST_QUARK (FORMAT))));
265
266   gst_structure_id_set (s,
267       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
268       GST_QUARK (CURRENT), G_TYPE_INT64, cur, NULL);
269 }
270
271 /**
272  * gst_query_parse_position:
273  * @query: a #GstQuery
274  * @format: (out) (allow-none): the storage for the #GstFormat of the
275  *     position values (may be %NULL)
276  * @cur: (out) (allow-none): the storage for the current position (may be %NULL)
277  *
278  * Parse a position query, writing the format into @format, and the position
279  * into @cur, if the respective parameters are non-%NULL.
280  */
281 void
282 gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
283 {
284   GstStructure *structure;
285
286   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
287
288   structure = GST_QUERY_STRUCTURE (query);
289   if (format)
290     *format =
291         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
292             GST_QUARK (FORMAT)));
293   if (cur)
294     *cur = g_value_get_int64 (gst_structure_id_get_value (structure,
295             GST_QUARK (CURRENT)));
296 }
297
298
299 /**
300  * gst_query_new_duration:
301  * @format: the #GstFormat for this duration query
302  *
303  * Constructs a new stream duration query object to query in the given format.
304  * Use gst_query_unref() when done with it. A duration query will give the
305  * total length of the stream.
306  *
307  * Free-function: gst_query_unref()
308  *
309  * Returns: (transfer full): a new #GstQuery
310  */
311 GstQuery *
312 gst_query_new_duration (GstFormat format)
313 {
314   GstQuery *query;
315   GstStructure *structure;
316
317   structure = gst_structure_new_id (GST_QUARK (QUERY_DURATION),
318       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
319       GST_QUARK (DURATION), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
320
321   query = gst_query_new_custom (GST_QUERY_DURATION, structure);
322
323   return query;
324 }
325
326 /**
327  * gst_query_set_duration:
328  * @query: a #GstQuery
329  * @format: the #GstFormat for the duration
330  * @duration: the duration of the stream
331  *
332  * Answer a duration query by setting the requested value in the given format.
333  */
334 void
335 gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration)
336 {
337   GstStructure *s;
338
339   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
340
341   s = GST_QUERY_STRUCTURE (query);
342   g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s,
343               GST_QUARK (FORMAT))));
344   gst_structure_id_set (s, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
345       GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL);
346 }
347
348 /**
349  * gst_query_parse_duration:
350  * @query: a #GstQuery
351  * @format: (out) (allow-none): the storage for the #GstFormat of the duration
352  *     value, or %NULL.
353  * @duration: (out) (allow-none): the storage for the total duration, or %NULL.
354  *
355  * Parse a duration query answer. Write the format of the duration into @format,
356  * and the value into @duration, if the respective variables are non-%NULL.
357  */
358 void
359 gst_query_parse_duration (GstQuery * query, GstFormat * format,
360     gint64 * duration)
361 {
362   GstStructure *structure;
363
364   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
365
366   structure = GST_QUERY_STRUCTURE (query);
367   if (format)
368     *format =
369         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
370             GST_QUARK (FORMAT)));
371   if (duration)
372     *duration = g_value_get_int64 (gst_structure_id_get_value (structure,
373             GST_QUARK (DURATION)));
374 }
375
376 /**
377  * gst_query_new_latency:
378  *
379  * Constructs a new latency query object.
380  * Use gst_query_unref() when done with it. A latency query is usually performed
381  * by sinks to compensate for additional latency introduced by elements in the
382  * pipeline.
383  *
384  * Free-function: gst_query_unref()
385  *
386  * Returns: (transfer full): a #GstQuery
387  */
388 GstQuery *
389 gst_query_new_latency (void)
390 {
391   GstQuery *query;
392   GstStructure *structure;
393
394   structure = gst_structure_new_id (GST_QUARK (QUERY_LATENCY),
395       GST_QUARK (LIVE), G_TYPE_BOOLEAN, FALSE,
396       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
397       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, GST_CLOCK_TIME_NONE, NULL);
398
399   query = gst_query_new_custom (GST_QUERY_LATENCY, structure);
400
401   return query;
402 }
403
404 /**
405  * gst_query_set_latency:
406  * @query: a #GstQuery
407  * @live: if there is a live element upstream
408  * @min_latency: the minimal latency of the upstream elements
409  * @max_latency: the maximal latency of the upstream elements
410  *
411  * Answer a latency query by setting the requested values in the given format.
412  */
413 void
414 gst_query_set_latency (GstQuery * query, gboolean live,
415     GstClockTime min_latency, GstClockTime max_latency)
416 {
417   GstStructure *structure;
418
419   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
420   g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
421
422   structure = GST_QUERY_STRUCTURE (query);
423   gst_structure_id_set (structure,
424       GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
425       GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, min_latency,
426       GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, max_latency, NULL);
427 }
428
429 /**
430  * gst_query_parse_latency:
431  * @query: a #GstQuery
432  * @live: (out) (allow-none): storage for live or %NULL
433  * @min_latency: (out) (allow-none): the storage for the min latency or %NULL
434  * @max_latency: (out) (allow-none): the storage for the max latency or %NULL
435  *
436  * Parse a latency query answer.
437  */
438 void
439 gst_query_parse_latency (GstQuery * query, gboolean * live,
440     GstClockTime * min_latency, GstClockTime * max_latency)
441 {
442   GstStructure *structure;
443
444   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY);
445
446   structure = GST_QUERY_STRUCTURE (query);
447   if (live)
448     *live =
449         g_value_get_boolean (gst_structure_id_get_value (structure,
450             GST_QUARK (LIVE)));
451   if (min_latency)
452     *min_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
453             GST_QUARK (MIN_LATENCY)));
454   if (max_latency)
455     *max_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
456             GST_QUARK (MAX_LATENCY)));
457 }
458
459 /**
460  * gst_query_new_convert:
461  * @src_format: the source #GstFormat for the new query
462  * @value: the value to convert
463  * @dest_format: the target #GstFormat
464  *
465  * Constructs a new convert query object. Use gst_query_unref()
466  * when done with it. A convert query is used to ask for a conversion between
467  * one format and another.
468  *
469  * Free-function: gst_query_unref()
470  *
471  * Returns: (transfer full): a #GstQuery
472  */
473 GstQuery *
474 gst_query_new_convert (GstFormat src_format, gint64 value,
475     GstFormat dest_format)
476 {
477   GstQuery *query;
478   GstStructure *structure;
479
480   structure = gst_structure_new_id (GST_QUARK (QUERY_CONVERT),
481       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
482       GST_QUARK (SRC_VALUE), G_TYPE_INT64, value,
483       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
484       GST_QUARK (DEST_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
485
486   query = gst_query_new_custom (GST_QUERY_CONVERT, structure);
487
488   return query;
489 }
490
491 /**
492  * gst_query_set_convert:
493  * @query: a #GstQuery
494  * @src_format: the source #GstFormat
495  * @src_value: the source value
496  * @dest_format: the destination #GstFormat
497  * @dest_value: the destination value
498  *
499  * Answer a convert query by setting the requested values.
500  */
501 void
502 gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value,
503     GstFormat dest_format, gint64 dest_value)
504 {
505   GstStructure *structure;
506
507   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
508
509   structure = GST_QUERY_STRUCTURE (query);
510   gst_structure_id_set (structure,
511       GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
512       GST_QUARK (SRC_VALUE), G_TYPE_INT64, src_value,
513       GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
514       GST_QUARK (DEST_VALUE), G_TYPE_INT64, dest_value, NULL);
515 }
516
517 /**
518  * gst_query_parse_convert:
519  * @query: a #GstQuery
520  * @src_format: (out) (allow-none): the storage for the #GstFormat of the
521  *     source value, or %NULL
522  * @src_value: (out) (allow-none): the storage for the source value, or %NULL
523  * @dest_format: (out) (allow-none): the storage for the #GstFormat of the
524  *     destination value, or %NULL
525  * @dest_value: (out) (allow-none): the storage for the destination value,
526  *     or %NULL
527  *
528  * Parse a convert query answer. Any of @src_format, @src_value, @dest_format,
529  * and @dest_value may be %NULL, in which case that value is omitted.
530  */
531 void
532 gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
533     gint64 * src_value, GstFormat * dest_format, gint64 * dest_value)
534 {
535   GstStructure *structure;
536
537   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
538
539   structure = GST_QUERY_STRUCTURE (query);
540   if (src_format)
541     *src_format =
542         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
543             GST_QUARK (SRC_FORMAT)));
544   if (src_value)
545     *src_value = g_value_get_int64 (gst_structure_id_get_value (structure,
546             GST_QUARK (SRC_VALUE)));
547   if (dest_format)
548     *dest_format =
549         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
550             GST_QUARK (DEST_FORMAT)));
551   if (dest_value)
552     *dest_value = g_value_get_int64 (gst_structure_id_get_value (structure,
553             GST_QUARK (DEST_VALUE)));
554 }
555
556 /**
557  * gst_query_new_segment:
558  * @format: the #GstFormat for the new query
559  *
560  * Constructs a new segment query object. Use gst_query_unref()
561  * when done with it. A segment query is used to discover information about the
562  * currently configured segment for playback.
563  *
564  * Free-function: gst_query_unref()
565  *
566  * Returns: (transfer full): a new #GstQuery
567  */
568 GstQuery *
569 gst_query_new_segment (GstFormat format)
570 {
571   GstQuery *query;
572   GstStructure *structure;
573
574   structure = gst_structure_new_id (GST_QUARK (QUERY_SEGMENT),
575       GST_QUARK (RATE), G_TYPE_DOUBLE, (gdouble) 0.0,
576       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
577       GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
578       GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
579
580   query = gst_query_new_custom (GST_QUERY_SEGMENT, structure);
581
582   return query;
583 }
584
585 /**
586  * gst_query_set_segment:
587  * @query: a #GstQuery
588  * @rate: the rate of the segment
589  * @format: the #GstFormat of the segment values (@start_value and @stop_value)
590  * @start_value: the start value
591  * @stop_value: the stop value
592  *
593  * Answer a segment query by setting the requested values. The normal
594  * playback segment of a pipeline is 0 to duration at the default rate of
595  * 1.0. If a seek was performed on the pipeline to play a different
596  * segment, this query will return the range specified in the last seek.
597  *
598  * @start_value and @stop_value will respectively contain the configured
599  * playback range start and stop values expressed in @format.
600  * The values are always between 0 and the duration of the media and
601  * @start_value <= @stop_value. @rate will contain the playback rate. For
602  * negative rates, playback will actually happen from @stop_value to
603  * @start_value.
604  */
605 void
606 gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format,
607     gint64 start_value, gint64 stop_value)
608 {
609   GstStructure *structure;
610
611   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
612
613   structure = GST_QUERY_STRUCTURE (query);
614   gst_structure_id_set (structure,
615       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
616       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
617       GST_QUARK (START_VALUE), G_TYPE_INT64, start_value,
618       GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop_value, NULL);
619 }
620
621 /**
622  * gst_query_parse_segment:
623  * @query: a #GstQuery
624  * @rate: (out) (allow-none): the storage for the rate of the segment, or %NULL
625  * @format: (out) (allow-none): the storage for the #GstFormat of the values,
626  *     or %NULL
627  * @start_value: (out) (allow-none): the storage for the start value, or %NULL
628  * @stop_value: (out) (allow-none): the storage for the stop value, or %NULL
629  *
630  * Parse a segment query answer. Any of @rate, @format, @start_value, and
631  * @stop_value may be %NULL, which will cause this value to be omitted.
632  *
633  * See gst_query_set_segment() for an explanation of the function arguments.
634  */
635 void
636 gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
637     gint64 * start_value, gint64 * stop_value)
638 {
639   GstStructure *structure;
640
641   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
642
643   structure = GST_QUERY_STRUCTURE (query);
644   if (rate)
645     *rate = g_value_get_double (gst_structure_id_get_value (structure,
646             GST_QUARK (RATE)));
647   if (format)
648     *format =
649         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
650             GST_QUARK (FORMAT)));
651   if (start_value)
652     *start_value = g_value_get_int64 (gst_structure_id_get_value (structure,
653             GST_QUARK (START_VALUE)));
654   if (stop_value)
655     *stop_value = g_value_get_int64 (gst_structure_id_get_value (structure,
656             GST_QUARK (STOP_VALUE)));
657 }
658
659 /**
660  * gst_query_new_custom:
661  * @type: the query type
662  * @structure: (allow-none) (transfer full): a structure for the query
663  *
664  * Constructs a new custom query object. Use gst_query_unref()
665  * when done with it.
666  *
667  * Free-function: gst_query_unref()
668  *
669  * Returns: (transfer full) (nullable): a new #GstQuery
670  */
671 GstQuery *
672 gst_query_new_custom (GstQueryType type, GstStructure * structure)
673 {
674   GstQueryImpl *query;
675
676   query = g_slice_new0 (GstQueryImpl);
677
678   GST_DEBUG ("creating new query %p %s", query, gst_query_type_get_name (type));
679
680   if (structure) {
681     /* structure must not have a parent */
682     if (!gst_structure_set_parent_refcount (structure,
683             &query->query.mini_object.refcount))
684       goto had_parent;
685   }
686
687   gst_mini_object_init (GST_MINI_OBJECT_CAST (query), 0, _gst_query_type,
688       (GstMiniObjectCopyFunction) _gst_query_copy, NULL,
689       (GstMiniObjectFreeFunction) _gst_query_free);
690
691   GST_QUERY_TYPE (query) = type;
692   GST_QUERY_STRUCTURE (query) = structure;
693
694   return GST_QUERY_CAST (query);
695
696   /* ERRORS */
697 had_parent:
698   {
699     g_slice_free1 (sizeof (GstQueryImpl), query);
700     g_warning ("structure is already owned by another object");
701     return NULL;
702   }
703 }
704
705 /**
706  * gst_query_get_structure:
707  * @query: a #GstQuery
708  *
709  * Get the structure of a query.
710  *
711  * Returns: (transfer none) (nullable): the #GstStructure of the query. The
712  *     structure is still owned by the query and will therefore be freed when the
713  *     query is unreffed.
714  */
715 const GstStructure *
716 gst_query_get_structure (GstQuery * query)
717 {
718   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
719
720   return GST_QUERY_STRUCTURE (query);
721 }
722
723 /**
724  * gst_query_writable_structure:
725  * @query: a #GstQuery
726  *
727  * Get the structure of a query. This method should be called with a writable
728  * @query so that the returned structure is guaranteed to be writable.
729  *
730  * Returns: (transfer none): the #GstStructure of the query. The structure is
731  *     still owned by the query and will therefore be freed when the query
732  *     is unreffed.
733  */
734 GstStructure *
735 gst_query_writable_structure (GstQuery * query)
736 {
737   GstStructure *structure;
738
739   g_return_val_if_fail (GST_IS_QUERY (query), NULL);
740   g_return_val_if_fail (gst_query_is_writable (query), NULL);
741
742   structure = GST_QUERY_STRUCTURE (query);
743
744   if (structure == NULL) {
745     structure =
746         gst_structure_new_id_empty (gst_query_type_to_quark (GST_QUERY_TYPE
747             (query)));
748     gst_structure_set_parent_refcount (structure, &query->mini_object.refcount);
749     GST_QUERY_STRUCTURE (query) = structure;
750   }
751   return structure;
752 }
753
754 /**
755  * gst_query_new_seeking:
756  * @format: the default #GstFormat for the new query
757  *
758  * Constructs a new query object for querying seeking properties of
759  * the stream.
760  *
761  * Free-function: gst_query_unref()
762  *
763  * Returns: (transfer full): a new #GstQuery
764  */
765 GstQuery *
766 gst_query_new_seeking (GstFormat format)
767 {
768   GstQuery *query;
769   GstStructure *structure;
770
771   structure = gst_structure_new_id (GST_QUARK (QUERY_SEEKING),
772       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
773       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, FALSE,
774       GST_QUARK (SEGMENT_START), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
775       GST_QUARK (SEGMENT_END), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
776
777   query = gst_query_new_custom (GST_QUERY_SEEKING, structure);
778
779   return query;
780 }
781
782 /**
783  * gst_query_set_seeking:
784  * @query: a #GstQuery
785  * @format: the format to set for the @segment_start and @segment_end values
786  * @seekable: the seekable flag to set
787  * @segment_start: the segment_start to set
788  * @segment_end: the segment_end to set
789  *
790  * Set the seeking query result fields in @query.
791  */
792 void
793 gst_query_set_seeking (GstQuery * query, GstFormat format,
794     gboolean seekable, gint64 segment_start, gint64 segment_end)
795 {
796   GstStructure *structure;
797
798   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
799   g_return_if_fail (gst_query_is_writable (query));
800
801   structure = GST_QUERY_STRUCTURE (query);
802   gst_structure_id_set (structure,
803       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
804       GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable,
805       GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start,
806       GST_QUARK (SEGMENT_END), G_TYPE_INT64, segment_end, NULL);
807 }
808
809 /**
810  * gst_query_parse_seeking:
811  * @query: a GST_QUERY_SEEKING type query #GstQuery
812  * @format: (out) (allow-none): the format to set for the @segment_start
813  *     and @segment_end values, or %NULL
814  * @seekable: (out) (allow-none): the seekable flag to set, or %NULL
815  * @segment_start: (out) (allow-none): the segment_start to set, or %NULL
816  * @segment_end: (out) (allow-none): the segment_end to set, or %NULL
817  *
818  * Parse a seeking query, writing the format into @format, and
819  * other results into the passed parameters, if the respective parameters
820  * are non-%NULL
821  */
822 void
823 gst_query_parse_seeking (GstQuery * query, GstFormat * format,
824     gboolean * seekable, gint64 * segment_start, gint64 * segment_end)
825 {
826   GstStructure *structure;
827
828   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEEKING);
829
830   structure = GST_QUERY_STRUCTURE (query);
831   if (format)
832     *format =
833         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
834             GST_QUARK (FORMAT)));
835   if (seekable)
836     *seekable = g_value_get_boolean (gst_structure_id_get_value (structure,
837             GST_QUARK (SEEKABLE)));
838   if (segment_start)
839     *segment_start = g_value_get_int64 (gst_structure_id_get_value (structure,
840             GST_QUARK (SEGMENT_START)));
841   if (segment_end)
842     *segment_end = g_value_get_int64 (gst_structure_id_get_value (structure,
843             GST_QUARK (SEGMENT_END)));
844 }
845
846 static GArray *
847 ensure_array (GstStructure * s, GQuark quark, gsize element_size,
848     GDestroyNotify clear_func)
849 {
850   GArray *array;
851   const GValue *value;
852
853   value = gst_structure_id_get_value (s, quark);
854   if (value) {
855     array = (GArray *) g_value_get_boxed (value);
856   } else {
857     GValue new_array_val = { 0, };
858
859     array = g_array_new (FALSE, TRUE, element_size);
860     if (clear_func)
861       g_array_set_clear_func (array, clear_func);
862
863     g_value_init (&new_array_val, G_TYPE_ARRAY);
864     g_value_take_boxed (&new_array_val, array);
865
866     gst_structure_id_take_value (s, quark, &new_array_val);
867   }
868   return array;
869 }
870
871 /**
872  * gst_query_new_formats:
873  *
874  * Constructs a new query object for querying formats of
875  * the stream.
876  *
877  * Free-function: gst_query_unref()
878  *
879  * Returns: (transfer full): a new #GstQuery
880  */
881 GstQuery *
882 gst_query_new_formats (void)
883 {
884   GstQuery *query;
885   GstStructure *structure;
886
887   structure = gst_structure_new_id_empty (GST_QUARK (QUERY_FORMATS));
888   query = gst_query_new_custom (GST_QUERY_FORMATS, structure);
889
890   return query;
891 }
892
893 static void
894 gst_query_list_add_format (GValue * list, GstFormat format)
895 {
896   GValue item = { 0, };
897
898   g_value_init (&item, GST_TYPE_FORMAT);
899   g_value_set_enum (&item, format);
900   gst_value_list_append_value (list, &item);
901   g_value_unset (&item);
902 }
903
904 /**
905  * gst_query_set_formats:
906  * @query: a #GstQuery
907  * @n_formats: the number of formats to set.
908  * @...: A number of @GstFormats equal to @n_formats.
909  *
910  * Set the formats query result fields in @query. The number of formats passed
911  * must be equal to @n_formats.
912  */
913 void
914 gst_query_set_formats (GstQuery * query, gint n_formats, ...)
915 {
916   va_list ap;
917   GValue list = { 0, };
918   gint i;
919   GstStructure *structure;
920
921   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
922   g_return_if_fail (gst_query_is_writable (query));
923
924   g_value_init (&list, GST_TYPE_LIST);
925
926   va_start (ap, n_formats);
927   for (i = 0; i < n_formats; i++) {
928     gst_query_list_add_format (&list, va_arg (ap, GstFormat));
929   }
930   va_end (ap);
931
932   structure = GST_QUERY_STRUCTURE (query);
933   gst_structure_set_value (structure, "formats", &list);
934
935   g_value_unset (&list);
936
937 }
938
939 /**
940  * gst_query_set_formatsv:
941  * @query: a #GstQuery
942  * @n_formats: the number of formats to set.
943  * @formats: (in) (array length=n_formats): an array containing @n_formats
944  *     @GstFormat values.
945  *
946  * Set the formats query result fields in @query. The number of formats passed
947  * in the @formats array must be equal to @n_formats.
948  */
949 void
950 gst_query_set_formatsv (GstQuery * query, gint n_formats,
951     const GstFormat * formats)
952 {
953   GValue list = { 0, };
954   gint i;
955   GstStructure *structure;
956
957   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
958   g_return_if_fail (gst_query_is_writable (query));
959
960   g_value_init (&list, GST_TYPE_LIST);
961   for (i = 0; i < n_formats; i++) {
962     gst_query_list_add_format (&list, formats[i]);
963   }
964   structure = GST_QUERY_STRUCTURE (query);
965   gst_structure_set_value (structure, "formats", &list);
966
967   g_value_unset (&list);
968 }
969
970 /**
971  * gst_query_parse_n_formats:
972  * @query: a #GstQuery
973  * @n_formats: (out) (allow-none): the number of formats in this query.
974  *
975  * Parse the number of formats in the formats @query.
976  */
977 void
978 gst_query_parse_n_formats (GstQuery * query, guint * n_formats)
979 {
980   GstStructure *structure;
981
982   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
983
984   if (n_formats) {
985     const GValue *list;
986
987     structure = GST_QUERY_STRUCTURE (query);
988     list = gst_structure_get_value (structure, "formats");
989     if (list == NULL)
990       *n_formats = 0;
991     else
992       *n_formats = gst_value_list_get_size (list);
993   }
994 }
995
996 /**
997  * gst_query_parse_nth_format:
998  * @query: a #GstQuery
999  * @nth: the nth format to retrieve.
1000  * @format: (out) (allow-none): a pointer to store the nth format
1001  *
1002  * Parse the format query and retrieve the @nth format from it into
1003  * @format. If the list contains less elements than @nth, @format will be
1004  * set to GST_FORMAT_UNDEFINED.
1005  */
1006 void
1007 gst_query_parse_nth_format (GstQuery * query, guint nth, GstFormat * format)
1008 {
1009   GstStructure *structure;
1010
1011   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);
1012
1013   if (format) {
1014     const GValue *list;
1015
1016     structure = GST_QUERY_STRUCTURE (query);
1017     list = gst_structure_get_value (structure, "formats");
1018     if (list == NULL) {
1019       *format = GST_FORMAT_UNDEFINED;
1020     } else {
1021       if (nth < gst_value_list_get_size (list)) {
1022         *format =
1023             (GstFormat) g_value_get_enum (gst_value_list_get_value (list, nth));
1024       } else
1025         *format = GST_FORMAT_UNDEFINED;
1026     }
1027   }
1028 }
1029
1030 /**
1031  * gst_query_new_buffering:
1032  * @format: the default #GstFormat for the new query
1033  *
1034  * Constructs a new query object for querying the buffering status of
1035  * a stream.
1036  *
1037  * Free-function: gst_query_unref()
1038  *
1039  * Returns: (transfer full): a new #GstQuery
1040  */
1041 GstQuery *
1042 gst_query_new_buffering (GstFormat format)
1043 {
1044   GstQuery *query;
1045   GstStructure *structure;
1046
1047   /* by default, we configure the answer as no buffering with a 100% buffering
1048    * progress */
1049   structure = gst_structure_new_id (GST_QUARK (QUERY_BUFFERING),
1050       GST_QUARK (BUSY), G_TYPE_BOOLEAN, FALSE,
1051       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, 100,
1052       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
1053       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
1054       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
1055       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, G_GINT64_CONSTANT (0),
1056       GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
1057       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1058       GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
1059       GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
1060
1061   query = gst_query_new_custom (GST_QUERY_BUFFERING, structure);
1062
1063   return query;
1064 }
1065
1066 /**
1067  * gst_query_set_buffering_percent:
1068  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1069  * @busy: if buffering is busy
1070  * @percent: a buffering percent
1071  *
1072  * Set the percentage of buffered data. This is a value between 0 and 100.
1073  * The @busy indicator is %TRUE when the buffering is in progress.
1074  */
1075 void
1076 gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent)
1077 {
1078   GstStructure *structure;
1079
1080   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1081   g_return_if_fail (gst_query_is_writable (query));
1082   g_return_if_fail (percent >= 0 && percent <= 100);
1083
1084   structure = GST_QUERY_STRUCTURE (query);
1085   gst_structure_id_set (structure,
1086       GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy,
1087       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL);
1088 }
1089
1090 /**
1091  * gst_query_parse_buffering_percent:
1092  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1093  * @busy: (out) (allow-none): if buffering is busy, or %NULL
1094  * @percent: (out) (allow-none): a buffering percent, or %NULL
1095  *
1096  * Get the percentage of buffered data. This is a value between 0 and 100.
1097  * The @busy indicator is %TRUE when the buffering is in progress.
1098  */
1099 void
1100 gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy,
1101     gint * percent)
1102 {
1103   GstStructure *structure;
1104
1105   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1106
1107   structure = GST_QUERY_STRUCTURE (query);
1108   if (busy)
1109     *busy = g_value_get_boolean (gst_structure_id_get_value (structure,
1110             GST_QUARK (BUSY)));
1111   if (percent)
1112     *percent = g_value_get_int (gst_structure_id_get_value (structure,
1113             GST_QUARK (BUFFER_PERCENT)));
1114 }
1115
1116 /**
1117  * gst_query_set_buffering_stats:
1118  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1119  * @mode: a buffering mode
1120  * @avg_in: the average input rate
1121  * @avg_out: the average output rate
1122  * @buffering_left: amount of buffering time left in milliseconds
1123  *
1124  * Configures the buffering stats values in @query.
1125  */
1126 void
1127 gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode,
1128     gint avg_in, gint avg_out, gint64 buffering_left)
1129 {
1130   GstStructure *structure;
1131
1132   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1133   g_return_if_fail (gst_query_is_writable (query));
1134
1135   structure = GST_QUERY_STRUCTURE (query);
1136   gst_structure_id_set (structure,
1137       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
1138       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
1139       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
1140       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
1141 }
1142
1143 /**
1144  * gst_query_parse_buffering_stats:
1145  * @query: A valid #GstQuery of type GST_QUERY_BUFFERING.
1146  * @mode: (out) (allow-none): a buffering mode, or %NULL
1147  * @avg_in: (out) (allow-none): the average input rate, or %NULL
1148  * @avg_out: (out) (allow-none): the average output rat, or %NULL
1149  * @buffering_left: (out) (allow-none): amount of buffering time left in
1150  *     milliseconds, or %NULL
1151  *
1152  * Extracts the buffering stats values from @query.
1153  */
1154 void
1155 gst_query_parse_buffering_stats (GstQuery * query,
1156     GstBufferingMode * mode, gint * avg_in, gint * avg_out,
1157     gint64 * buffering_left)
1158 {
1159   GstStructure *structure;
1160
1161   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1162
1163   structure = GST_QUERY_STRUCTURE (query);
1164   if (mode)
1165     *mode = (GstBufferingMode)
1166         g_value_get_enum (gst_structure_id_get_value (structure,
1167             GST_QUARK (BUFFERING_MODE)));
1168   if (avg_in)
1169     *avg_in = g_value_get_int (gst_structure_id_get_value (structure,
1170             GST_QUARK (AVG_IN_RATE)));
1171   if (avg_out)
1172     *avg_out = g_value_get_int (gst_structure_id_get_value (structure,
1173             GST_QUARK (AVG_OUT_RATE)));
1174   if (buffering_left)
1175     *buffering_left =
1176         g_value_get_int64 (gst_structure_id_get_value (structure,
1177             GST_QUARK (BUFFERING_LEFT)));
1178 }
1179
1180 /**
1181  * gst_query_set_buffering_range:
1182  * @query: a #GstQuery
1183  * @format: the format to set for the @start and @stop values
1184  * @start: the start to set
1185  * @stop: the stop to set
1186  * @estimated_total: estimated total amount of download time remaining in
1187  *     milliseconds
1188  *
1189  * Set the available query result fields in @query.
1190  */
1191 void
1192 gst_query_set_buffering_range (GstQuery * query, GstFormat format,
1193     gint64 start, gint64 stop, gint64 estimated_total)
1194 {
1195   GstStructure *structure;
1196
1197   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1198   g_return_if_fail (gst_query_is_writable (query));
1199
1200   structure = GST_QUERY_STRUCTURE (query);
1201   gst_structure_id_set (structure,
1202       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1203       GST_QUARK (START_VALUE), G_TYPE_INT64, start,
1204       GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop,
1205       GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, estimated_total, NULL);
1206 }
1207
1208 /**
1209  * gst_query_parse_buffering_range:
1210  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1211  * @format: (out) (allow-none): the format to set for the @segment_start
1212  *     and @segment_end values, or %NULL
1213  * @start: (out) (allow-none): the start to set, or %NULL
1214  * @stop: (out) (allow-none): the stop to set, or %NULL
1215  * @estimated_total: (out) (allow-none): estimated total amount of download
1216  *     time remaining in milliseconds, or %NULL
1217  *
1218  * Parse an available query, writing the format into @format, and
1219  * other results into the passed parameters, if the respective parameters
1220  * are non-%NULL
1221  */
1222 void
1223 gst_query_parse_buffering_range (GstQuery * query, GstFormat * format,
1224     gint64 * start, gint64 * stop, gint64 * estimated_total)
1225 {
1226   GstStructure *structure;
1227
1228   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING);
1229
1230   structure = GST_QUERY_STRUCTURE (query);
1231   if (format)
1232     *format =
1233         (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
1234             GST_QUARK (FORMAT)));
1235   if (start)
1236     *start = g_value_get_int64 (gst_structure_id_get_value (structure,
1237             GST_QUARK (START_VALUE)));
1238   if (stop)
1239     *stop = g_value_get_int64 (gst_structure_id_get_value (structure,
1240             GST_QUARK (STOP_VALUE)));
1241   if (estimated_total)
1242     *estimated_total =
1243         g_value_get_int64 (gst_structure_id_get_value (structure,
1244             GST_QUARK (ESTIMATED_TOTAL)));
1245 }
1246
1247 /* GstQueryBufferingRange: internal struct for GArray */
1248 typedef struct
1249 {
1250   gint64 start;
1251   gint64 stop;
1252 } GstQueryBufferingRange;
1253
1254 /**
1255  * gst_query_add_buffering_range:
1256  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1257  * @start: start position of the range
1258  * @stop: stop position of the range
1259  *
1260  * Set the buffering-ranges array field in @query. The current last
1261  * start position of the array should be inferior to @start.
1262  *
1263  * Returns: a #gboolean indicating if the range was added or not.
1264  */
1265 gboolean
1266 gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop)
1267 {
1268   GstQueryBufferingRange range;
1269   GstStructure *structure;
1270   GArray *array;
1271
1272   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE);
1273   g_return_val_if_fail (gst_query_is_writable (query), FALSE);
1274
1275   if (G_UNLIKELY (start >= stop))
1276     return FALSE;
1277
1278   structure = GST_QUERY_STRUCTURE (query);
1279   array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES),
1280       sizeof (GstQueryBufferingRange), NULL);
1281
1282   if (array->len > 1) {
1283     GstQueryBufferingRange *last;
1284
1285     last = &g_array_index (array, GstQueryBufferingRange, array->len - 1);
1286
1287     if (G_UNLIKELY (start <= last->start))
1288       return FALSE;
1289   }
1290
1291   range.start = start;
1292   range.stop = stop;
1293   g_array_append_val (array, range);
1294
1295   return TRUE;
1296 }
1297
1298 /**
1299  * gst_query_get_n_buffering_ranges:
1300  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1301  *
1302  * Retrieve the number of values currently stored in the
1303  * buffered-ranges array of the query's structure.
1304  *
1305  * Returns: the range array size as a #guint.
1306  */
1307 guint
1308 gst_query_get_n_buffering_ranges (GstQuery * query)
1309 {
1310   GstStructure *structure;
1311   GArray *array;
1312
1313   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, 0);
1314
1315   structure = GST_QUERY_STRUCTURE (query);
1316   array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES),
1317       sizeof (GstQueryBufferingRange), NULL);
1318
1319   return array->len;
1320 }
1321
1322
1323 /**
1324  * gst_query_parse_nth_buffering_range:
1325  * @query: a GST_QUERY_BUFFERING type query #GstQuery
1326  * @index: position in the buffered-ranges array to read
1327  * @start: (out) (allow-none): the start position to set, or %NULL
1328  * @stop: (out) (allow-none): the stop position to set, or %NULL
1329  *
1330  * Parse an available query and get the start and stop values stored
1331  * at the @index of the buffered ranges array.
1332  *
1333  * Returns: a #gboolean indicating if the parsing succeeded.
1334  */
1335 gboolean
1336 gst_query_parse_nth_buffering_range (GstQuery * query, guint index,
1337     gint64 * start, gint64 * stop)
1338 {
1339   GstQueryBufferingRange *range;
1340   GstStructure *structure;
1341   GArray *array;
1342
1343   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, FALSE);
1344
1345   structure = GST_QUERY_STRUCTURE (query);
1346
1347   array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES),
1348       sizeof (GstQueryBufferingRange), NULL);
1349   g_return_val_if_fail (index < array->len, FALSE);
1350
1351   range = &g_array_index (array, GstQueryBufferingRange, index);
1352
1353   if (start)
1354     *start = range->start;
1355   if (stop)
1356     *stop = range->stop;
1357
1358   return TRUE;
1359 }
1360
1361
1362 /**
1363  * gst_query_new_uri:
1364  *
1365  * Constructs a new query URI query object. Use gst_query_unref()
1366  * when done with it. An URI query is used to query the current URI
1367  * that is used by the source or sink.
1368  *
1369  * Free-function: gst_query_unref()
1370  *
1371  * Returns: (transfer full): a new #GstQuery
1372  */
1373 GstQuery *
1374 gst_query_new_uri (void)
1375 {
1376   GstQuery *query;
1377   GstStructure *structure;
1378
1379   structure = gst_structure_new_id (GST_QUARK (QUERY_URI),
1380       GST_QUARK (URI), G_TYPE_STRING, NULL, NULL);
1381
1382   query = gst_query_new_custom (GST_QUERY_URI, structure);
1383
1384   return query;
1385 }
1386
1387 /**
1388  * gst_query_set_uri:
1389  * @query: a #GstQuery with query type GST_QUERY_URI
1390  * @uri: the URI to set
1391  *
1392  * Answer a URI query by setting the requested URI.
1393  */
1394 void
1395 gst_query_set_uri (GstQuery * query, const gchar * uri)
1396 {
1397   GstStructure *structure;
1398
1399   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1400   g_return_if_fail (gst_query_is_writable (query));
1401   g_return_if_fail (gst_uri_is_valid (uri));
1402
1403   structure = GST_QUERY_STRUCTURE (query);
1404   gst_structure_id_set (structure, GST_QUARK (URI), G_TYPE_STRING, uri, NULL);
1405 }
1406
1407 /**
1408  * gst_query_parse_uri:
1409  * @query: a #GstQuery
1410  * @uri: (out) (transfer full) (allow-none): the storage for the current URI
1411  *     (may be %NULL)
1412  *
1413  * Parse an URI query, writing the URI into @uri as a newly
1414  * allocated string, if the respective parameters are non-%NULL.
1415  * Free the string with g_free() after usage.
1416  */
1417 void
1418 gst_query_parse_uri (GstQuery * query, gchar ** uri)
1419 {
1420   GstStructure *structure;
1421
1422   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1423
1424   structure = GST_QUERY_STRUCTURE (query);
1425   if (uri)
1426     *uri = g_value_dup_string (gst_structure_id_get_value (structure,
1427             GST_QUARK (URI)));
1428 }
1429
1430 /**
1431  * gst_query_set_uri_redirection:
1432  * @query: a #GstQuery with query type GST_QUERY_URI
1433  * @uri: the URI to set
1434  *
1435  * Answer a URI query by setting the requested URI redirection.
1436  *
1437  * Since: 1.2
1438  */
1439 void
1440 gst_query_set_uri_redirection (GstQuery * query, const gchar * uri)
1441 {
1442   GstStructure *structure;
1443
1444   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1445   g_return_if_fail (gst_query_is_writable (query));
1446   g_return_if_fail (gst_uri_is_valid (uri));
1447
1448   structure = GST_QUERY_STRUCTURE (query);
1449   gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION),
1450       G_TYPE_STRING, uri, NULL);
1451 }
1452
1453 /**
1454  * gst_query_parse_uri_redirection:
1455  * @query: a #GstQuery
1456  * @uri: (out) (transfer full) (allow-none): the storage for the redirect URI
1457  *     (may be %NULL)
1458  *
1459  * Parse an URI query, writing the URI into @uri as a newly
1460  * allocated string, if the respective parameters are non-%NULL.
1461  * Free the string with g_free() after usage.
1462  *
1463  * Since: 1.2
1464  */
1465 void
1466 gst_query_parse_uri_redirection (GstQuery * query, gchar ** uri)
1467 {
1468   GstStructure *structure;
1469
1470   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1471
1472   structure = GST_QUERY_STRUCTURE (query);
1473   if (uri) {
1474     if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION),
1475             G_TYPE_STRING, uri, NULL))
1476       *uri = NULL;
1477   }
1478 }
1479
1480 /**
1481  * gst_query_set_uri_redirection_permanent:
1482  * @query: a #GstQuery with query type %GST_QUERY_URI
1483  * @permanent: whether the redirect is permanent or not
1484  *
1485  * Answer a URI query by setting the requested URI redirection
1486  * to permanent or not.
1487  *
1488  * Since: 1.4
1489  */
1490 void
1491 gst_query_set_uri_redirection_permanent (GstQuery * query, gboolean permanent)
1492 {
1493   GstStructure *structure;
1494
1495   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1496   g_return_if_fail (gst_query_is_writable (query));
1497
1498   structure = GST_QUERY_STRUCTURE (query);
1499   gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION_PERMANENT),
1500       G_TYPE_BOOLEAN, permanent, NULL);
1501 }
1502
1503 /**
1504  * gst_query_parse_uri_redirection_permanent:
1505  * @query: a #GstQuery
1506  * @permanent: (out) (allow-none): if the URI redirection is permanent
1507  *     (may be %NULL)
1508  *
1509  * Parse an URI query, and set @permanent to %TRUE if there is a redirection
1510  * and it should be considered permanent. If a redirection is permanent,
1511  * applications should update their internal storage of the URI, otherwise
1512  * they should make all future requests to the original URI.
1513  *
1514  * Since: 1.4
1515  */
1516 void
1517 gst_query_parse_uri_redirection_permanent (GstQuery * query,
1518     gboolean * permanent)
1519 {
1520   GstStructure *structure;
1521
1522   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI);
1523
1524   structure = GST_QUERY_STRUCTURE (query);
1525   if (permanent) {
1526     if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION_PERMANENT),
1527             G_TYPE_BOOLEAN, permanent, NULL))
1528       *permanent = FALSE;
1529   }
1530 }
1531
1532 /**
1533  * gst_query_new_allocation:
1534  * @caps: the negotiated caps
1535  * @need_pool: return a pool
1536  *
1537  * Constructs a new query object for querying the allocation properties.
1538  *
1539  * Free-function: gst_query_unref()
1540  *
1541  * Returns: (transfer full): a new #GstQuery
1542  */
1543 GstQuery *
1544 gst_query_new_allocation (GstCaps * caps, gboolean need_pool)
1545 {
1546   GstQuery *query;
1547   GstStructure *structure;
1548
1549   structure = gst_structure_new_id (GST_QUARK (QUERY_ALLOCATION),
1550       GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
1551       GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
1552
1553   query = gst_query_new_custom (GST_QUERY_ALLOCATION, structure);
1554
1555   return query;
1556 }
1557
1558 /**
1559  * gst_query_parse_allocation:
1560  * @query: a #GstQuery
1561  * @caps: (out) (transfer none) (allow-none): The #GstCaps
1562  * @need_pool: (out) (allow-none): Whether a #GstBufferPool is needed
1563  *
1564  * Parse an allocation query, writing the requested caps in @caps and
1565  * whether a pool is needed in @need_pool, if the respective parameters
1566  * are non-%NULL.
1567  *
1568  * Pool details can be retrieved using gst_query_get_n_allocation_pools() and
1569  * gst_query_parse_nth_allocation_pool().
1570  */
1571 void
1572 gst_query_parse_allocation (GstQuery * query, GstCaps ** caps,
1573     gboolean * need_pool)
1574 {
1575   GstStructure *structure;
1576
1577   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1578
1579   structure = GST_QUERY_STRUCTURE (query);
1580   if (caps) {
1581     *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
1582             GST_QUARK (CAPS)));
1583   }
1584   gst_structure_id_get (structure,
1585       GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
1586 }
1587
1588 typedef struct
1589 {
1590   GstBufferPool *pool;
1591   guint size;
1592   guint min_buffers;
1593   guint max_buffers;
1594 } AllocationPool;
1595
1596 static void
1597 allocation_pool_free (AllocationPool * ap)
1598 {
1599   if (ap->pool)
1600     gst_object_unref (ap->pool);
1601 }
1602
1603 /**
1604  * gst_query_add_allocation_pool:
1605  * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
1606  * @pool: (transfer none) (allow-none): the #GstBufferPool
1607  * @size: the buffer size
1608  * @min_buffers: the min buffers
1609  * @max_buffers: the max buffers
1610  *
1611  * Set the pool parameters in @query.
1612  */
1613 void
1614 gst_query_add_allocation_pool (GstQuery * query, GstBufferPool * pool,
1615     guint size, guint min_buffers, guint max_buffers)
1616 {
1617   GArray *array;
1618   GstStructure *structure;
1619   AllocationPool ap;
1620
1621   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1622   g_return_if_fail (gst_query_is_writable (query));
1623
1624   structure = GST_QUERY_STRUCTURE (query);
1625   array = ensure_array (structure, GST_QUARK (POOL),
1626       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
1627
1628   if ((ap.pool = pool))
1629     gst_object_ref (pool);
1630   ap.size = size;
1631   ap.min_buffers = min_buffers;
1632   ap.max_buffers = max_buffers;
1633
1634   g_array_append_val (array, ap);
1635 }
1636
1637 /**
1638  * gst_query_get_n_allocation_pools:
1639  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1640  *
1641  * Retrieve the number of values currently stored in the
1642  * pool array of the query's structure.
1643  *
1644  * Returns: the pool array size as a #guint.
1645  */
1646 guint
1647 gst_query_get_n_allocation_pools (GstQuery * query)
1648 {
1649   GArray *array;
1650   GstStructure *structure;
1651
1652   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
1653
1654   structure = GST_QUERY_STRUCTURE (query);
1655   array = ensure_array (structure, GST_QUARK (POOL),
1656       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
1657
1658   return array->len;
1659 }
1660
1661 /**
1662  * gst_query_parse_nth_allocation_pool:
1663  * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
1664  * @index: index to parse
1665  * @pool: (out) (allow-none) (transfer full): the #GstBufferPool
1666  * @size: (out) (allow-none): the buffer size
1667  * @min_buffers: (out) (allow-none): the min buffers
1668  * @max_buffers: (out) (allow-none): the max buffers
1669  *
1670  * Get the pool parameters in @query.
1671  *
1672  * Unref @pool with gst_object_unref() when it's not needed any more.
1673  */
1674 void
1675 gst_query_parse_nth_allocation_pool (GstQuery * query, guint index,
1676     GstBufferPool ** pool, guint * size, guint * min_buffers,
1677     guint * max_buffers)
1678 {
1679   GArray *array;
1680   GstStructure *structure;
1681   AllocationPool *ap;
1682
1683   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1684
1685   structure = GST_QUERY_STRUCTURE (query);
1686   array = ensure_array (structure, GST_QUARK (POOL),
1687       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
1688   g_return_if_fail (index < array->len);
1689
1690   ap = &g_array_index (array, AllocationPool, index);
1691
1692   if (pool)
1693     if ((*pool = ap->pool))
1694       gst_object_ref (*pool);
1695   if (size)
1696     *size = ap->size;
1697   if (min_buffers)
1698     *min_buffers = ap->min_buffers;
1699   if (max_buffers)
1700     *max_buffers = ap->max_buffers;
1701 }
1702
1703 /**
1704  * gst_query_set_nth_allocation_pool:
1705  * @index: index to modify
1706  * @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
1707  * @pool: (transfer none) (allow-none): the #GstBufferPool
1708  * @size: the buffer size
1709  * @min_buffers: the min buffers
1710  * @max_buffers: the max buffers
1711  *
1712  * Set the pool parameters in @query.
1713  */
1714 void
1715 gst_query_set_nth_allocation_pool (GstQuery * query, guint index,
1716     GstBufferPool * pool, guint size, guint min_buffers, guint max_buffers)
1717 {
1718   GArray *array;
1719   GstStructure *structure;
1720   AllocationPool *oldap, ap;
1721
1722   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1723
1724   structure = GST_QUERY_STRUCTURE (query);
1725   array = ensure_array (structure, GST_QUARK (POOL),
1726       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
1727   g_return_if_fail (index < array->len);
1728
1729   oldap = &g_array_index (array, AllocationPool, index);
1730   allocation_pool_free (oldap);
1731
1732   if ((ap.pool = pool))
1733     gst_object_ref (pool);
1734   ap.size = size;
1735   ap.min_buffers = min_buffers;
1736   ap.max_buffers = max_buffers;
1737   g_array_index (array, AllocationPool, index) = ap;
1738 }
1739
1740 /**
1741  * gst_query_remove_nth_allocation_pool:
1742  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1743  * @index: position in the allocation pool array to remove
1744  *
1745  * Remove the allocation pool at @index of the allocation pool array.
1746  *
1747  * Since: 1.2
1748  */
1749 void
1750 gst_query_remove_nth_allocation_pool (GstQuery * query, guint index)
1751 {
1752   GArray *array;
1753   GstStructure *structure;
1754
1755   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1756   g_return_if_fail (gst_query_is_writable (query));
1757
1758   structure = GST_QUERY_STRUCTURE (query);
1759   array =
1760       ensure_array (structure, GST_QUARK (POOL), sizeof (AllocationPool),
1761       (GDestroyNotify) allocation_pool_free);
1762   g_return_if_fail (index < array->len);
1763
1764   g_array_remove_index (array, index);
1765 }
1766
1767 typedef struct
1768 {
1769   GType api;
1770   GstStructure *params;
1771 } AllocationMeta;
1772
1773 static void
1774 allocation_meta_free (AllocationMeta * am)
1775 {
1776   if (am->params)
1777     gst_structure_free (am->params);
1778 }
1779
1780 /**
1781  * gst_query_add_allocation_meta:
1782  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1783  * @api: the metadata API
1784  * @params: (transfer none) (allow-none): API specific parameters
1785  *
1786  * Add @api with @params as one of the supported metadata API to @query.
1787  */
1788 void
1789 gst_query_add_allocation_meta (GstQuery * query, GType api,
1790     const GstStructure * params)
1791 {
1792   GArray *array;
1793   GstStructure *structure;
1794   AllocationMeta am;
1795
1796   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1797   g_return_if_fail (api != 0);
1798   g_return_if_fail (gst_query_is_writable (query));
1799
1800   structure = GST_QUERY_STRUCTURE (query);
1801   array =
1802       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1803       (GDestroyNotify) allocation_meta_free);
1804
1805   am.api = api;
1806   am.params = (params ? gst_structure_copy (params) : NULL);
1807
1808   g_array_append_val (array, am);
1809 }
1810
1811 /**
1812  * gst_query_get_n_allocation_metas:
1813  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1814  *
1815  * Retrieve the number of values currently stored in the
1816  * meta API array of the query's structure.
1817  *
1818  * Returns: the metadata API array size as a #guint.
1819  */
1820 guint
1821 gst_query_get_n_allocation_metas (GstQuery * query)
1822 {
1823   GArray *array;
1824   GstStructure *structure;
1825
1826   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
1827
1828   structure = GST_QUERY_STRUCTURE (query);
1829   array =
1830       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1831       (GDestroyNotify) allocation_meta_free);
1832
1833   return array->len;
1834 }
1835
1836 /**
1837  * gst_query_parse_nth_allocation_meta:
1838  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1839  * @index: position in the metadata API array to read
1840  * @params: (out) (transfer none) (allow-none): API specific parameters
1841  *
1842  * Parse an available query and get the metadata API
1843  * at @index of the metadata API array.
1844  *
1845  * Returns: a #GType of the metadata API at @index.
1846  */
1847 GType
1848 gst_query_parse_nth_allocation_meta (GstQuery * query, guint index,
1849     const GstStructure ** params)
1850 {
1851   GArray *array;
1852   GstStructure *structure;
1853   AllocationMeta *am;
1854
1855   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
1856
1857   structure = GST_QUERY_STRUCTURE (query);
1858   array =
1859       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1860       (GDestroyNotify) allocation_meta_free);
1861
1862   g_return_val_if_fail (index < array->len, 0);
1863
1864   am = &g_array_index (array, AllocationMeta, index);
1865
1866   if (params)
1867     *params = am->params;
1868
1869   return am->api;
1870 }
1871
1872 /**
1873  * gst_query_remove_nth_allocation_meta:
1874  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1875  * @index: position in the metadata API array to remove
1876  *
1877  * Remove the metadata API at @index of the metadata API array.
1878  */
1879 void
1880 gst_query_remove_nth_allocation_meta (GstQuery * query, guint index)
1881 {
1882   GArray *array;
1883   GstStructure *structure;
1884
1885   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1886   g_return_if_fail (gst_query_is_writable (query));
1887
1888   structure = GST_QUERY_STRUCTURE (query);
1889   array =
1890       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1891       (GDestroyNotify) allocation_meta_free);
1892   g_return_if_fail (index < array->len);
1893
1894   g_array_remove_index (array, index);
1895 }
1896
1897 /**
1898  * gst_query_find_allocation_meta:
1899  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1900  * @api: the metadata API
1901  * @index: (out) (transfer none) (allow-none): the index
1902  *
1903  * Check if @query has metadata @api set. When this function returns %TRUE,
1904  * @index will contain the index where the requested API and the parameters
1905  * can be found.
1906  *
1907  * Returns: %TRUE when @api is in the list of metadata.
1908  */
1909 gboolean
1910 gst_query_find_allocation_meta (GstQuery * query, GType api, guint * index)
1911 {
1912   GArray *array;
1913   GstStructure *structure;
1914   guint i, len;
1915
1916   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, FALSE);
1917   g_return_val_if_fail (api != 0, FALSE);
1918
1919   structure = GST_QUERY_STRUCTURE (query);
1920   array =
1921       ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
1922       (GDestroyNotify) allocation_meta_free);
1923
1924   len = array->len;
1925   for (i = 0; i < len; i++) {
1926     AllocationMeta *am = &g_array_index (array, AllocationMeta, i);
1927     if (am->api == api) {
1928       if (index)
1929         *index = i;
1930       return TRUE;
1931     }
1932   }
1933   return FALSE;
1934 }
1935
1936 typedef struct
1937 {
1938   GstAllocator *allocator;
1939   GstAllocationParams params;
1940 } AllocationParam;
1941
1942 static void
1943 allocation_param_free (AllocationParam * ap)
1944 {
1945   if (ap->allocator)
1946     gst_object_unref (ap->allocator);
1947 }
1948
1949 /**
1950  * gst_query_add_allocation_param:
1951  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1952  * @allocator: (transfer none) (allow-none): the memory allocator
1953  * @params: (transfer none) (allow-none): a #GstAllocationParams
1954  *
1955  * Add @allocator and its @params as a supported memory allocator.
1956  */
1957 void
1958 gst_query_add_allocation_param (GstQuery * query, GstAllocator * allocator,
1959     const GstAllocationParams * params)
1960 {
1961   GArray *array;
1962   GstStructure *structure;
1963   AllocationParam ap;
1964
1965   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
1966   g_return_if_fail (gst_query_is_writable (query));
1967   g_return_if_fail (allocator != NULL || params != NULL);
1968
1969   structure = GST_QUERY_STRUCTURE (query);
1970   array = ensure_array (structure, GST_QUARK (ALLOCATOR),
1971       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
1972
1973   if ((ap.allocator = allocator))
1974     gst_object_ref (allocator);
1975   if (params)
1976     ap.params = *params;
1977   else
1978     gst_allocation_params_init (&ap.params);
1979
1980   g_array_append_val (array, ap);
1981 }
1982
1983 /**
1984  * gst_query_get_n_allocation_params:
1985  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
1986  *
1987  * Retrieve the number of values currently stored in the
1988  * allocator params array of the query's structure.
1989  *
1990  * If no memory allocator is specified, the downstream element can handle
1991  * the default memory allocator. The first memory allocator in the query
1992  * should be generic and allow mapping to system memory, all following
1993  * allocators should be ordered by preference with the preferred one first.
1994  *
1995  * Returns: the allocator array size as a #guint.
1996  */
1997 guint
1998 gst_query_get_n_allocation_params (GstQuery * query)
1999 {
2000   GArray *array;
2001   GstStructure *structure;
2002
2003   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
2004
2005   structure = GST_QUERY_STRUCTURE (query);
2006   array = ensure_array (structure, GST_QUARK (ALLOCATOR),
2007       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
2008
2009   return array->len;
2010 }
2011
2012 /**
2013  * gst_query_parse_nth_allocation_param:
2014  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
2015  * @index: position in the allocator array to read
2016  * @allocator: (out) (transfer full) (allow-none): variable to hold the result
2017  * @params: (out) (allow-none): parameters for the allocator
2018  *
2019  * Parse an available query and get the allocator and its params
2020  * at @index of the allocator array.
2021  */
2022 void
2023 gst_query_parse_nth_allocation_param (GstQuery * query, guint index,
2024     GstAllocator ** allocator, GstAllocationParams * params)
2025 {
2026   GArray *array;
2027   GstStructure *structure;
2028   AllocationParam *ap;
2029
2030   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
2031
2032   structure = GST_QUERY_STRUCTURE (query);
2033   array = ensure_array (structure, GST_QUARK (ALLOCATOR),
2034       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
2035   g_return_if_fail (index < array->len);
2036
2037   ap = &g_array_index (array, AllocationParam, index);
2038
2039   if (allocator)
2040     if ((*allocator = ap->allocator))
2041       gst_object_ref (*allocator);
2042   if (params)
2043     *params = ap->params;
2044 }
2045
2046 /**
2047  * gst_query_set_nth_allocation_param:
2048  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
2049  * @index: position in the allocator array to set
2050  * @allocator: (transfer none) (allow-none): new allocator to set
2051  * @params: (transfer none) (allow-none): parameters for the allocator
2052  *
2053  * Parse an available query and get the allocator and its params
2054  * at @index of the allocator array.
2055  */
2056 void
2057 gst_query_set_nth_allocation_param (GstQuery * query, guint index,
2058     GstAllocator * allocator, const GstAllocationParams * params)
2059 {
2060   GArray *array;
2061   GstStructure *structure;
2062   AllocationParam *old, ap;
2063
2064   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
2065
2066   structure = GST_QUERY_STRUCTURE (query);
2067   array = ensure_array (structure, GST_QUARK (ALLOCATOR),
2068       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
2069   g_return_if_fail (index < array->len);
2070
2071   old = &g_array_index (array, AllocationParam, index);
2072   allocation_param_free (old);
2073
2074   if ((ap.allocator = allocator))
2075     gst_object_ref (allocator);
2076   if (params)
2077     ap.params = *params;
2078   else
2079     gst_allocation_params_init (&ap.params);
2080
2081   g_array_index (array, AllocationParam, index) = ap;
2082 }
2083
2084 /**
2085  * gst_query_remove_nth_allocation_param:
2086  * @query: a GST_QUERY_ALLOCATION type query #GstQuery
2087  * @index: position in the allocation param array to remove
2088  *
2089  * Remove the allocation param at @index of the allocation param array.
2090  *
2091  * Since: 1.2
2092  */
2093 void
2094 gst_query_remove_nth_allocation_param (GstQuery * query, guint index)
2095 {
2096   GArray *array;
2097   GstStructure *structure;
2098
2099   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
2100   g_return_if_fail (gst_query_is_writable (query));
2101
2102   structure = GST_QUERY_STRUCTURE (query);
2103   array =
2104       ensure_array (structure, GST_QUARK (ALLOCATOR), sizeof (AllocationParam),
2105       (GDestroyNotify) allocation_param_free);
2106   g_return_if_fail (index < array->len);
2107
2108   g_array_remove_index (array, index);
2109 }
2110
2111 /**
2112  * gst_query_new_scheduling:
2113  *
2114  * Constructs a new query object for querying the scheduling properties.
2115  *
2116  * Free-function: gst_query_unref()
2117  *
2118  * Returns: (transfer full): a new #GstQuery
2119  */
2120 GstQuery *
2121 gst_query_new_scheduling (void)
2122 {
2123   GstQuery *query;
2124   GstStructure *structure;
2125
2126   structure = gst_structure_new_id (GST_QUARK (QUERY_SCHEDULING),
2127       GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, 0,
2128       GST_QUARK (MINSIZE), G_TYPE_INT, 1,
2129       GST_QUARK (MAXSIZE), G_TYPE_INT, -1,
2130       GST_QUARK (ALIGN), G_TYPE_INT, 0, NULL);
2131   query = gst_query_new_custom (GST_QUERY_SCHEDULING, structure);
2132
2133   return query;
2134 }
2135
2136 /**
2137  * gst_query_set_scheduling:
2138  * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING.
2139  * @flags: #GstSchedulingFlags
2140  * @minsize: the suggested minimum size of pull requests
2141  * @maxsize: the suggested maximum size of pull requests
2142  * @align: the suggested alignment of pull requests
2143  *
2144  * Set the scheduling properties.
2145  */
2146 void
2147 gst_query_set_scheduling (GstQuery * query, GstSchedulingFlags flags,
2148     gint minsize, gint maxsize, gint align)
2149 {
2150   GstStructure *structure;
2151
2152   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
2153   g_return_if_fail (gst_query_is_writable (query));
2154
2155   structure = GST_QUERY_STRUCTURE (query);
2156   gst_structure_id_set (structure,
2157       GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags,
2158       GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
2159       GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
2160       GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
2161 }
2162
2163 /**
2164  * gst_query_parse_scheduling:
2165  * @query: A valid #GstQuery of type GST_QUERY_SCHEDULING.
2166  * @flags: (out) (allow-none): #GstSchedulingFlags
2167  * @minsize: (out) (allow-none): the suggested minimum size of pull requests
2168  * @maxsize: (out) (allow-none): the suggested maximum size of pull requests:
2169  * @align: (out) (allow-none): the suggested alignment of pull requests
2170  *
2171  * Set the scheduling properties.
2172  */
2173 void
2174 gst_query_parse_scheduling (GstQuery * query, GstSchedulingFlags * flags,
2175     gint * minsize, gint * maxsize, gint * align)
2176 {
2177   GstStructure *structure;
2178
2179   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
2180
2181   structure = GST_QUERY_STRUCTURE (query);
2182   gst_structure_id_get (structure,
2183       GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags,
2184       GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
2185       GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
2186       GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
2187 }
2188
2189 /**
2190  * gst_query_add_scheduling_mode:
2191  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2192  * @mode: a #GstPadMode
2193  *
2194  * Add @mode as one of the supported scheduling modes to @query.
2195  */
2196 void
2197 gst_query_add_scheduling_mode (GstQuery * query, GstPadMode mode)
2198 {
2199   GstStructure *structure;
2200   GArray *array;
2201
2202   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
2203   g_return_if_fail (gst_query_is_writable (query));
2204
2205   structure = GST_QUERY_STRUCTURE (query);
2206   array =
2207       ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
2208
2209   g_array_append_val (array, mode);
2210 }
2211
2212 /**
2213  * gst_query_get_n_scheduling_modes:
2214  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2215  *
2216  * Retrieve the number of values currently stored in the
2217  * scheduling mode array of the query's structure.
2218  *
2219  * Returns: the scheduling mode array size as a #guint.
2220  */
2221 guint
2222 gst_query_get_n_scheduling_modes (GstQuery * query)
2223 {
2224   GArray *array;
2225   GstStructure *structure;
2226
2227   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, 0);
2228
2229   structure = GST_QUERY_STRUCTURE (query);
2230   array =
2231       ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
2232
2233   return array->len;
2234 }
2235
2236 /**
2237  * gst_query_parse_nth_scheduling_mode:
2238  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2239  * @index: position in the scheduling modes array to read
2240  *
2241  * Parse an available query and get the scheduling mode
2242  * at @index of the scheduling modes array.
2243  *
2244  * Returns: a #GstPadMode of the scheduling mode at @index.
2245  */
2246 GstPadMode
2247 gst_query_parse_nth_scheduling_mode (GstQuery * query, guint index)
2248 {
2249   GstStructure *structure;
2250   GArray *array;
2251
2252   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING,
2253       GST_PAD_MODE_NONE);
2254
2255   structure = GST_QUERY_STRUCTURE (query);
2256   array =
2257       ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
2258   g_return_val_if_fail (index < array->len, GST_PAD_MODE_NONE);
2259
2260   return g_array_index (array, GstPadMode, index);
2261 }
2262
2263 /**
2264  * gst_query_has_scheduling_mode:
2265  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2266  * @mode: the scheduling mode
2267  *
2268  * Check if @query has scheduling mode set.
2269  *
2270  * > When checking if upstream supports pull mode, it is usually not
2271  * > enough to just check for GST_PAD_MODE_PULL with this function, you
2272  * > also want to check whether the scheduling flags returned by
2273  * > gst_query_parse_scheduling() have the seeking flag set (meaning
2274  * > random access is supported, not only sequential pulls).
2275  *
2276  * Returns: %TRUE when @mode is in the list of scheduling modes.
2277  */
2278 gboolean
2279 gst_query_has_scheduling_mode (GstQuery * query, GstPadMode mode)
2280 {
2281   GstStructure *structure;
2282   GArray *array;
2283   guint i, len;
2284
2285   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE);
2286
2287   structure = GST_QUERY_STRUCTURE (query);
2288   array =
2289       ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
2290
2291   len = array->len;
2292   for (i = 0; i < len; i++) {
2293     if (mode == g_array_index (array, GstPadMode, i))
2294       return TRUE;
2295   }
2296   return FALSE;
2297 }
2298
2299 /**
2300  * gst_query_has_scheduling_mode_with_flags:
2301  * @query: a GST_QUERY_SCHEDULING type query #GstQuery
2302  * @mode: the scheduling mode
2303  * @flags: #GstSchedulingFlags
2304  *
2305  * Check if @query has scheduling mode set and @flags is set in
2306  * query scheduling flags.
2307  *
2308  * Returns: %TRUE when @mode is in the list of scheduling modes
2309  *    and @flags are compatible with query flags.
2310  */
2311 gboolean
2312 gst_query_has_scheduling_mode_with_flags (GstQuery * query, GstPadMode mode,
2313     GstSchedulingFlags flags)
2314 {
2315   GstSchedulingFlags sched_flags;
2316
2317   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE);
2318
2319   gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL);
2320
2321   return ((flags & sched_flags) == flags) &&
2322       gst_query_has_scheduling_mode (query, mode);
2323 }
2324
2325 /**
2326  * gst_query_new_accept_caps:
2327  * @caps: a fixed #GstCaps
2328  *
2329  * Constructs a new query object for querying if @caps are accepted.
2330  *
2331  * Free-function: gst_query_unref()
2332  *
2333  * Returns: (transfer full): a new #GstQuery
2334  */
2335 GstQuery *
2336 gst_query_new_accept_caps (GstCaps * caps)
2337 {
2338   GstQuery *query;
2339   GstStructure *structure;
2340
2341   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
2342
2343   structure = gst_structure_new_id (GST_QUARK (QUERY_ACCEPT_CAPS),
2344       GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
2345       GST_QUARK (RESULT), G_TYPE_BOOLEAN, FALSE, NULL);
2346   query = gst_query_new_custom (GST_QUERY_ACCEPT_CAPS, structure);
2347
2348   return query;
2349 }
2350
2351 /**
2352  * gst_query_parse_accept_caps:
2353  * @query: The query to parse
2354  * @caps: (out) (transfer none): A pointer to the caps
2355  *
2356  * Get the caps from @query. The caps remains valid as long as @query remains
2357  * valid.
2358  */
2359 void
2360 gst_query_parse_accept_caps (GstQuery * query, GstCaps ** caps)
2361 {
2362   GstStructure *structure;
2363
2364   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
2365   g_return_if_fail (caps != NULL);
2366
2367   structure = GST_QUERY_STRUCTURE (query);
2368   *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
2369           GST_QUARK (CAPS)));
2370 }
2371
2372 /**
2373  * gst_query_set_accept_caps_result:
2374  * @query: a GST_QUERY_ACCEPT_CAPS type query #GstQuery
2375  * @result: the result to set
2376  *
2377  * Set @result as the result for the @query.
2378  */
2379 void
2380 gst_query_set_accept_caps_result (GstQuery * query, gboolean result)
2381 {
2382   GstStructure *structure;
2383
2384   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
2385   g_return_if_fail (gst_query_is_writable (query));
2386
2387   structure = GST_QUERY_STRUCTURE (query);
2388   gst_structure_id_set (structure,
2389       GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL);
2390 }
2391
2392 /**
2393  * gst_query_parse_accept_caps_result:
2394  * @query: a GST_QUERY_ACCEPT_CAPS type query #GstQuery
2395  * @result: (out) (allow-none): location for the result
2396  *
2397  * Parse the result from @query and store in @result.
2398  */
2399 void
2400 gst_query_parse_accept_caps_result (GstQuery * query, gboolean * result)
2401 {
2402   GstStructure *structure;
2403
2404   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
2405
2406   structure = GST_QUERY_STRUCTURE (query);
2407   gst_structure_id_get (structure,
2408       GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL);
2409 }
2410
2411 /**
2412  * gst_query_new_caps:
2413  * @filter: a filter
2414  *
2415  * Constructs a new query object for querying the caps.
2416  *
2417  * The CAPS query should return the allowable caps for a pad in the context
2418  * of the element's state, its link to other elements, and the devices or files
2419  * it has opened. These caps must be a subset of the pad template caps. In the
2420  * NULL state with no links, the CAPS query should ideally return the same caps
2421  * as the pad template. In rare circumstances, an object property can affect
2422  * the caps returned by the CAPS query, but this is discouraged.
2423  *
2424  * For most filters, the caps returned by CAPS query is directly affected by the
2425  * allowed caps on other pads. For demuxers and decoders, the caps returned by
2426  * the srcpad's getcaps function is directly related to the stream data. Again,
2427  * the CAPS query should return the most specific caps it reasonably can, since this
2428  * helps with autoplugging.
2429  *
2430  * The @filter is used to restrict the result caps, only the caps matching
2431  * @filter should be returned from the CAPS query. Specifying a filter might
2432  * greatly reduce the amount of processing an element needs to do.
2433  *
2434  * Free-function: gst_query_unref()
2435  *
2436  * Returns: (transfer full): a new #GstQuery
2437  */
2438 GstQuery *
2439 gst_query_new_caps (GstCaps * filter)
2440 {
2441   GstQuery *query;
2442   GstStructure *structure;
2443
2444   structure = gst_structure_new_id (GST_QUARK (QUERY_CAPS),
2445       GST_QUARK (FILTER), GST_TYPE_CAPS, filter,
2446       GST_QUARK (CAPS), GST_TYPE_CAPS, NULL, NULL);
2447   query = gst_query_new_custom (GST_QUERY_CAPS, structure);
2448
2449   return query;
2450 }
2451
2452 /**
2453  * gst_query_parse_caps:
2454  * @query: The query to parse
2455  * @filter: (out) (transfer none): A pointer to the caps filter
2456  *
2457  * Get the filter from the caps @query. The caps remains valid as long as
2458  * @query remains valid.
2459  */
2460 void
2461 gst_query_parse_caps (GstQuery * query, GstCaps ** filter)
2462 {
2463   GstStructure *structure;
2464
2465   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
2466   g_return_if_fail (filter != NULL);
2467
2468   structure = GST_QUERY_STRUCTURE (query);
2469   *filter = g_value_get_boxed (gst_structure_id_get_value (structure,
2470           GST_QUARK (FILTER)));
2471 }
2472
2473 /**
2474  * gst_query_set_caps_result:
2475  * @query: The query to use
2476  * @caps: (in): A pointer to the caps
2477  *
2478  * Set the @caps result in @query.
2479  */
2480 void
2481 gst_query_set_caps_result (GstQuery * query, GstCaps * caps)
2482 {
2483   GstStructure *structure;
2484
2485   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
2486   g_return_if_fail (gst_query_is_writable (query));
2487
2488   structure = GST_QUERY_STRUCTURE (query);
2489   gst_structure_id_set (structure, GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL);
2490 }
2491
2492 /**
2493  * gst_query_parse_caps_result:
2494  * @query: The query to parse
2495  * @caps: (out) (transfer none): A pointer to the caps
2496  *
2497  * Get the caps result from @query. The caps remains valid as long as
2498  * @query remains valid.
2499  */
2500 void
2501 gst_query_parse_caps_result (GstQuery * query, GstCaps ** caps)
2502 {
2503   GstStructure *structure;
2504
2505   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
2506   g_return_if_fail (caps != NULL);
2507
2508   structure = GST_QUERY_STRUCTURE (query);
2509   *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
2510           GST_QUARK (CAPS)));
2511 }
2512
2513 #if 0
2514 void
2515 gst_query_intersect_caps_result (GstQuery * query, GstCaps * filter,
2516     GstCapsIntersectMode mode)
2517 {
2518   GstCaps *res, *caps = NULL;
2519
2520   gst_query_parse_caps_result (query, &caps);
2521   res = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
2522   gst_query_set_caps_result (query, res);
2523   gst_caps_unref (res);
2524 }
2525 #endif
2526
2527 /**
2528  * gst_query_new_drain:
2529  *
2530  * Constructs a new query object for querying the drain state.
2531  *
2532  * Free-function: gst_query_unref()
2533  *
2534  * Returns: (transfer full): a new #GstQuery
2535  */
2536 GstQuery *
2537 gst_query_new_drain (void)
2538 {
2539   GstQuery *query;
2540   GstStructure *structure;
2541
2542   structure = gst_structure_new_id_empty (GST_QUARK (QUERY_DRAIN));
2543   query = gst_query_new_custom (GST_QUERY_DRAIN, structure);
2544
2545   return query;
2546 }
2547
2548 /**
2549  * gst_query_new_context:
2550  * @context_type: Context type to query
2551  *
2552  * Constructs a new query object for querying the pipeline-local context.
2553  *
2554  * Free-function: gst_query_unref()
2555  *
2556  * Returns: (transfer full): a new #GstQuery
2557  *
2558  * Since: 1.2
2559  */
2560 GstQuery *
2561 gst_query_new_context (const gchar * context_type)
2562 {
2563   GstQuery *query;
2564   GstStructure *structure;
2565
2566   g_return_val_if_fail (context_type != NULL, NULL);
2567
2568   structure = gst_structure_new_id (GST_QUARK (QUERY_CONTEXT),
2569       GST_QUARK (CONTEXT_TYPE), G_TYPE_STRING, context_type, NULL);
2570   query = gst_query_new_custom (GST_QUERY_CONTEXT, structure);
2571
2572   return query;
2573 }
2574
2575 /**
2576  * gst_query_set_context:
2577  * @query: a #GstQuery with query type GST_QUERY_CONTEXT
2578  * @context: the requested #GstContext
2579  *
2580  * Answer a context query by setting the requested context.
2581  *
2582  * Since: 1.2
2583  */
2584 void
2585 gst_query_set_context (GstQuery * query, GstContext * context)
2586 {
2587   GstStructure *s;
2588   const gchar *context_type;
2589
2590   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT);
2591
2592   gst_query_parse_context_type (query, &context_type);
2593   g_return_if_fail (strcmp (gst_context_get_context_type (context),
2594           context_type) == 0);
2595
2596   s = GST_QUERY_STRUCTURE (query);
2597
2598   gst_structure_id_set (s,
2599       GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
2600 }
2601
2602 /**
2603  * gst_query_parse_context:
2604  * @query: The query to parse
2605  * @context: (out) (transfer none): A pointer to store the #GstContext
2606  *
2607  * Get the context from the context @query. The context remains valid as long as
2608  * @query remains valid.
2609  *
2610  * Since: 1.2
2611  */
2612 void
2613 gst_query_parse_context (GstQuery * query, GstContext ** context)
2614 {
2615   GstStructure *structure;
2616   const GValue *v;
2617
2618   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT);
2619   g_return_if_fail (context != NULL);
2620
2621   structure = GST_QUERY_STRUCTURE (query);
2622   v = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT));
2623   if (v)
2624     *context = g_value_get_boxed (v);
2625   else
2626     *context = NULL;
2627 }
2628
2629 /**
2630  * gst_query_parse_context_type:
2631  * @query: a GST_QUERY_CONTEXT type query
2632  * @context_type: (out) (transfer none) (allow-none): the context type, or %NULL
2633  *
2634  * Parse a context type from an existing GST_QUERY_CONTEXT query.
2635  *
2636  * Returns: a #gboolean indicating if the parsing succeeded.
2637  *
2638  * Since: 1.2
2639  */
2640 gboolean
2641 gst_query_parse_context_type (GstQuery * query, const gchar ** context_type)
2642 {
2643   GstStructure *structure;
2644   const GValue *value;
2645
2646   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT, FALSE);
2647
2648   structure = GST_QUERY_STRUCTURE (query);
2649
2650   if (context_type) {
2651     value = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT_TYPE));
2652     *context_type = g_value_get_string (value);
2653   }
2654
2655   return TRUE;
2656 }