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