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