1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * GData Client
4  * Copyright (C) Philip Withnall 2009–2010 <philip@tecnocode.co.uk>
5  *
6  * GData Client is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * GData Client is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 /**
21  * SECTION:gdata-youtube-query
22  * @short_description: GData YouTube query object
23  * @stability: Stable
24  * @include: gdata/services/youtube/gdata-youtube-query.h
25  *
26  * #GDataYouTubeQuery represents a collection of query parameters specific to the YouTube service, which go above and beyond
27  * those catered for by #GDataQuery.
28  *
29  * With the transition to version 3 of the YouTube, the #GDataQuery:author and
30  * #GDataQuery:start-index properties are no longer supported, and their values
31  * will be ignored. Use gdata_query_next_page() instead of the
32  * #GDataQuery:start-index API.
33  *
34  * For more information on the custom GData query parameters supported by #GDataYouTubeQuery, see the <ulink type="http"
35  * url="https://developers.google.com/youtube/v3/docs/search/list#parameters">online documentation</ulink>.
36  *
37  * Since: 0.3.0
38  */
39 
40 #include <config.h>
41 #include <glib.h>
42 #include <glib/gi18n-lib.h>
43 #include <string.h>
44 
45 #include "gdata-youtube-query.h"
46 #include "gdata-query.h"
47 #include "gdata-youtube-content.h"
48 #include "gdata-private.h"
49 
50 static void gdata_youtube_query_finalize (GObject *object);
51 static void gdata_youtube_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
52 static void gdata_youtube_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
53 static void get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started);
54 
55 struct _GDataYouTubeQueryPrivate {
56 	G_GNUC_BEGIN_IGNORE_DEPRECATIONS
57 	GDataYouTubeFormat format;
58 	GDataYouTubeSortOrder sort_order;
59 	GDataYouTubeUploader uploader;
60 	G_GNUC_END_IGNORE_DEPRECATIONS
61 
62 	gdouble latitude;
63 	gdouble longitude;
64 	gdouble location_radius;
65 	gboolean has_location;
66 	gchar *language;
67 	gchar *order_by;
68 	gchar *restriction;
69 	GDataYouTubeSafeSearch safe_search;
70 	GDataYouTubeAge age;
71 	gchar *license;
72 };
73 
74 enum {
75 	PROP_FORMAT = 1,
76 	PROP_LATITUDE,
77 	PROP_LONGITUDE,
78 	PROP_LOCATION_RADIUS,
79 	PROP_HAS_LOCATION,
80 	PROP_LANGUAGE,
81 	PROP_ORDER_BY,
82 	PROP_RESTRICTION,
83 	PROP_SAFE_SEARCH,
84 	PROP_SORT_ORDER,
85 	PROP_AGE,
86 	PROP_UPLOADER,
87 	PROP_LICENSE,
88 };
89 
G_DEFINE_TYPE(GDataYouTubeQuery,gdata_youtube_query,GDATA_TYPE_QUERY)90 G_DEFINE_TYPE (GDataYouTubeQuery, gdata_youtube_query, GDATA_TYPE_QUERY)
91 
92 static void
93 gdata_youtube_query_class_init (GDataYouTubeQueryClass *klass)
94 {
95 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
96 	GDataQueryClass *query_class = GDATA_QUERY_CLASS (klass);
97 
98 	g_type_class_add_private (klass, sizeof (GDataYouTubeQueryPrivate));
99 
100 	gobject_class->set_property = gdata_youtube_query_set_property;
101 	gobject_class->get_property = gdata_youtube_query_get_property;
102 	gobject_class->finalize = gdata_youtube_query_finalize;
103 
104 	query_class->get_query_uri = get_query_uri;
105 
106 	/**
107 	 * GDataYouTubeQuery:format:
108 	 *
109 	 * Specifies that videos must be available in a particular video format. Use %GDATA_YOUTUBE_FORMAT_UNKNOWN to
110 	 * retrieve videos irrespective of their format availability.
111 	 *
112 	 * Since: 0.3.0
113 	 * Deprecated: 0.17.0: No longer supported by Google. The value of
114 	 *   this property will be unused in queries. There is no replacement.
115 	 */
116 	g_object_class_install_property (gobject_class, PROP_FORMAT,
117 	                                 g_param_spec_enum ("format",
118 	                                                    "Format", "Specifies that videos must be available in a particular video format.",
119 	                                                    GDATA_TYPE_YOUTUBE_FORMAT, GDATA_YOUTUBE_FORMAT_UNKNOWN,
120 	                                                    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
121 	                                                    G_PARAM_DEPRECATED));
122 
123 	/**
124 	 * GDataYouTubeQuery:latitude:
125 	 *
126 	 * The latitude of a particular location of which videos should be found. This should be used in conjunction with
127 	 * #GDataYouTubeQuery:longitude; if either property is outside the valid range, neither will be used. Valid latitudes
128 	 * are between <code class="literal">-90</code> and <code class="literal">90</code>0 degrees; any values of this property outside that range
129 	 * will unset the property in the query URI.
130 	 *
131 	 * If #GDataYouTubeQuery:location-radius is a non-<code class="literal">0</code> value, this will define a circle from which videos should be
132 	 * found.
133 	 *
134 	 * As it is deprecated, the value of #GDataYouTubeQuery:has-location is
135 	 * ignored.
136 	 *
137 	 * For more information, see the <ulink type="http"
138 	 * url="https://developers.google.com/youtube/v3/docs/search/list#location">online documentation</ulink>.
139 	 *
140 	 * Since: 0.3.0
141 	 */
142 	g_object_class_install_property (gobject_class, PROP_LATITUDE,
143 	                                 g_param_spec_double ("latitude",
144 	                                                      "Latitude", "The latitude of a particular location of which videos should be found.",
145 	                                                      -G_MAXDOUBLE, G_MAXDOUBLE, G_MAXDOUBLE,
146 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
147 
148 	/**
149 	 * GDataYouTubeQuery:longitude:
150 	 *
151 	 * The longitude of a particular location of which videos should be found. This should be used in conjunction with
152 	 * #GDataYouTubeQuery:latitude; if either property is outside the valid range, neither will be used. Valid longitudes
153 	 * are between <code class="literal">-180</code> and <code class="literal">180</code> degrees; any values of this property outside that
154 	 * range will unset the property in the query URI.
155 	 *
156 	 * For more information, see the documentation for #GDataYouTubeQuery:latitude.
157 	 *
158 	 * Since: 0.3.0
159 	 */
160 	g_object_class_install_property (gobject_class, PROP_LONGITUDE,
161 	                                 g_param_spec_double ("longitude",
162 	                                                      "Longitude", "The longitude of a particular location of which videos should be found.",
163 	                                                      -G_MAXDOUBLE, G_MAXDOUBLE, G_MAXDOUBLE,
164 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
165 
166 	/**
167 	 * GDataYouTubeQuery:location-radius:
168 	 *
169 	 * The radius, in metres, of a circle from within which videos should be returned. The circle is centred on the latitude and
170 	 * longitude given in #GDataYouTubeQuery:latitude and #GDataYouTubeQuery:longitude.
171 	 *
172 	 * Set this property to <code class="literal">0</code> to search for specific coordinates, rather than within a given radius.
173 	 *
174 	 * For more information, see the documentation for #GDataYouTubeQuery:latitude.
175 	 *
176 	 * Since: 0.3.0
177 	 */
178 	g_object_class_install_property (gobject_class, PROP_LOCATION_RADIUS,
179 	                                 g_param_spec_double ("location-radius",
180 	                                                      "Location radius", "The radius, in metres, of a circle to search within.",
181 	                                                      0.0, G_MAXDOUBLE, 0.0,
182 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
183 
184 	/**
185 	 * GDataYouTubeQuery:has-location:
186 	 *
187 	 * Whether to restrict search results to videos with specific coordinates associated with them. If used with a given
188 	 * #GDataYouTubeQuery:latitude and #GDataYouTubeQuery:longitude, only videos with specific coordinates (not those with merely
189 	 * a descriptive address) will be returned. If used without a latitude and longitude set, only videos with specific coordinates
190 	 * (regardless of those coordinates) will be returned.
191 	 *
192 	 * For more information, see the documentation for #GDataYouTubeQuery:latitude.
193 	 *
194 	 * Since: 0.3.0
195 	 * Deprecated: 0.17.0: No longer supported by Google. The value of
196 	 *   this property will be unused in queries.
197 	 */
198 	g_object_class_install_property (gobject_class, PROP_HAS_LOCATION,
199 	                                 g_param_spec_boolean ("has-location",
200 	                                                       "Has location?", "Whether to restrict results to videos with specific coordinates.",
201 	                                                       FALSE,
202 	                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
203 	                                                       G_PARAM_DEPRECATED));
204 
205 	/**
206 	 * GDataYouTubeQuery:language:
207 	 *
208 	 * Restricts the search to videos that have a title, description or keywords in a specified language. The language code should
209 	 * be a two-letter ISO 639-1 code; or you can use <literal>zh-Hans</literal> for simplified Chinese and <literal>zh-Hant</literal>
210 	 * for traditional Chinese.
211 	 *
212 	 * For more information, see the <ulink type="http"
213 	 * url="http://code.google.com/apis/youtube/2.0/reference.html#lrsp">online documentation</ulink>.
214 	 *
215 	 * Since: 0.3.0
216 	 * Deprecated: 0.17.0: No longer supported by Google. The value of
217 	 *   this property will be unused in queries. There is no replacement.
218 	 */
219 	g_object_class_install_property (gobject_class, PROP_LANGUAGE,
220 	                                 g_param_spec_string ("language",
221 	                                                      "Language", "Restricts the search to videos described in the given language.",
222 	                                                      NULL,
223 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
224 	                                                      G_PARAM_DEPRECATED));
225 
226 	/**
227 	 * GDataYouTubeQuery:order-by:
228 	 *
229 	 * Specifies the order of entries in a feed. Supported values are <literal>relevance</literal>,
230 	 * <literal>published</literal>, <literal>viewCount</literal> and <literal>rating</literal>.
231 	 *
232 	 * Additionally, results most relevant to a specific language can be returned by setting the property
233 	 * to <literal>relevance_lang_<replaceable>languageCode</replaceable></literal>, where
234 	 * <replaceable>languageCode</replaceable> is an ISO 639-1 language code, as used in #GDataYouTubeQuery:language.
235 	 *
236 	 * For more information, see the <ulink type="http"
237 	 * url="https://developers.google.com/youtube/v3/docs/search/list#order">online documentation</ulink>.
238 	 *
239 	 * Since: 0.3.0
240 	 */
241 	g_object_class_install_property (gobject_class, PROP_ORDER_BY,
242 	                                 g_param_spec_string ("order-by",
243 	                                                      "Order by", "Specifies the order of entries in a feed.",
244 	                                                      NULL,
245 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
246 
247 	/**
248 	 * GDataYouTubeQuery:restriction:
249 	 *
250 	 * An ISO 3166 two-letter country code that should be used to filter
251 	 * videos playable only in specific countries.
252 	 *
253 	 * Previously, this property could also accept the client’s IP address
254 	 * for country lookup. This feature is no longer supported by Google,
255 	 * and will result in an error from the server if used. Use a country
256 	 * code instead.
257 	 *
258 	 * For more information, see the <ulink type="http"
259 	 * url="https://developers.google.com/youtube/v3/docs/search/list#regionCode">online documentation</ulink>.
260 	 *
261 	 * Since: 0.3.0
262 	 */
263 	g_object_class_install_property (gobject_class, PROP_RESTRICTION,
264 	                                 g_param_spec_string ("restriction",
265 	                                                      "Restriction", "The country code to filter videos playable only in specific countries.",
266 	                                                      NULL,
267 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
268 
269 	/**
270 	 * GDataYouTubeQuery:safe-search:
271 	 *
272 	 * Whether the search results should include restricted content as well as standard content.
273 	 *
274 	 * For more information, see the <ulink type="http"
275 	 * url="https://developers.google.com/youtube/v3/docs/search/list#safeSearch">online documentation</ulink>.
276 	 *
277 	 * Since: 0.3.0
278 	 */
279 	g_object_class_install_property (gobject_class, PROP_SAFE_SEARCH,
280 	                                 g_param_spec_enum ("safe-search",
281 	                                                    "Safe search", "Whether the search results should include restricted content.",
282 	                                                    GDATA_TYPE_YOUTUBE_SAFE_SEARCH, GDATA_YOUTUBE_SAFE_SEARCH_MODERATE,
283 	                                                    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
284 
285 	/**
286 	 * GDataYouTubeQuery:sort-order:
287 	 *
288 	 * Specifies the direction of sorting. To use the default sort order, set the property to %GDATA_YOUTUBE_SORT_NONE.
289 	 *
290 	 * Since: 0.3.0
291 	 * Deprecated: 0.17.0: No longer supported by Google. The value of
292 	 *   this property will be unused in queries. There is no replacement.
293 	 */
294 	g_object_class_install_property (gobject_class, PROP_SORT_ORDER,
295 	                                 g_param_spec_enum ("sort-order",
296 	                                                    "Sort order", "Specifies the direction of sorting.",
297 	                                                    GDATA_TYPE_YOUTUBE_SORT_ORDER, GDATA_YOUTUBE_SORT_NONE,
298 	                                                    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
299 	                                                    G_PARAM_DEPRECATED));
300 
301 	/**
302 	 * GDataYouTubeQuery:age:
303 	 *
304 	 * Restricts the search to videos uploaded within the specified time period. To retrieve videos irrespective of their
305 	 * age, set the property to %GDATA_YOUTUBE_AGE_ALL_TIME.
306 	 *
307 	 * Since: 0.3.0
308 	 */
309 	g_object_class_install_property (gobject_class, PROP_AGE,
310 	                                 g_param_spec_enum ("age",
311 	                                                    "Age", "Restricts the search to videos uploaded within the specified time period.",
312 	                                                    GDATA_TYPE_YOUTUBE_AGE, GDATA_YOUTUBE_AGE_ALL_TIME,
313 	                                                    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
314 
315 	/**
316 	 * GDataYouTubeQuery:uploader:
317 	 *
318 	 * Restricts the search to videos from the specified type of uploader. Currently, this can only be used to restrict
319 	 * searches to videos from YouTube partners.
320 	 *
321 	 * Since: 0.3.0
322 	 * Deprecated: 0.17.0: No longer supported by Google. The value of
323 	 *   this property will be unused in queries. There is no replacement.
324 	 */
325 	g_object_class_install_property (gobject_class, PROP_UPLOADER,
326 	                                 g_param_spec_enum ("uploader",
327 	                                                    "Uploader", "Restricts the search to videos from the specified type of uploader.",
328 	                                                    GDATA_TYPE_YOUTUBE_UPLOADER, GDATA_YOUTUBE_UPLOADER_ALL,
329 	                                                    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
330 	                                                    G_PARAM_DEPRECATED));
331 
332 	/**
333 	 * GDataYouTubeQuery:license:
334 	 *
335 	 * The content license which should be used to filter search results. If set to, for example, %GDATA_YOUTUBE_LICENSE_CC, only videos which
336 	 * are Creative Commons licensed will be returned in search results. Set this to %NULL to return videos under any license.
337 	 *
338 	 * For more information, see the <ulink type="http"
339 	 * url="https://developers.google.com/youtube/v3/docs/search/list#videoLicense">online documentation</ulink>.
340 	 *
341 	 * Since: 0.11.0
342 	 */
343 	g_object_class_install_property (gobject_class, PROP_LICENSE,
344 	                                 g_param_spec_string ("license",
345 	                                                      "License", "The content license which should be used to filter search results.",
346 	                                                      NULL,
347 	                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
348 
349 }
350 
351 static void
gdata_youtube_query_init(GDataYouTubeQuery * self)352 gdata_youtube_query_init (GDataYouTubeQuery *self)
353 {
354 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_YOUTUBE_QUERY, GDataYouTubeQueryPrivate);
355 
356 	self->priv->latitude = G_MAXDOUBLE;
357 	self->priv->longitude = G_MAXDOUBLE;
358 
359 	/* https://developers.google.com/youtube/v3/docs/search/list#pageToken */
360 	_gdata_query_set_pagination_type (GDATA_QUERY (self),
361 	                                  GDATA_QUERY_PAGINATION_TOKENS);
362 }
363 
364 static void
gdata_youtube_query_finalize(GObject * object)365 gdata_youtube_query_finalize (GObject *object)
366 {
367 	GDataYouTubeQueryPrivate *priv = GDATA_YOUTUBE_QUERY (object)->priv;
368 
369 	g_free (priv->language);
370 	g_free (priv->order_by);
371 	g_free (priv->restriction);
372 	g_free (priv->license);
373 
374 	/* Chain up to the parent class */
375 	G_OBJECT_CLASS (gdata_youtube_query_parent_class)->finalize (object);
376 }
377 
378 static void
gdata_youtube_query_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)379 gdata_youtube_query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
380 {
381 	GDataYouTubeQueryPrivate *priv = GDATA_YOUTUBE_QUERY (object)->priv;
382 
383 	switch (property_id) {
384 		case PROP_FORMAT:
385 			g_value_set_enum (value, priv->format);
386 			break;
387 		case PROP_LATITUDE:
388 			g_value_set_double (value, priv->latitude);
389 			break;
390 		case PROP_LONGITUDE:
391 			g_value_set_double (value, priv->longitude);
392 			break;
393 		case PROP_LOCATION_RADIUS:
394 			g_value_set_double (value, priv->location_radius);
395 			break;
396 		case PROP_HAS_LOCATION:
397 			g_value_set_boolean (value, priv->has_location);
398 			break;
399 		case PROP_LANGUAGE:
400 			g_value_set_string (value, priv->language);
401 			break;
402 		case PROP_ORDER_BY:
403 			g_value_set_string (value, priv->order_by);
404 			break;
405 		case PROP_RESTRICTION:
406 			g_value_set_string (value, priv->restriction);
407 			break;
408 		case PROP_SAFE_SEARCH:
409 			g_value_set_enum (value, priv->safe_search);
410 			break;
411 		case PROP_SORT_ORDER:
412 			g_value_set_enum (value, priv->sort_order);
413 			break;
414 		case PROP_AGE:
415 			g_value_set_enum (value, priv->age);
416 			break;
417 		case PROP_UPLOADER:
418 			g_value_set_enum (value, priv->uploader);
419 			break;
420 		case PROP_LICENSE:
421 			g_value_set_string (value, priv->license);
422 			break;
423 		default:
424 			/* We don't have any other property... */
425 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
426 			break;
427 	}
428 }
429 
430 static void
gdata_youtube_query_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)431 gdata_youtube_query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
432 {
433 	GDataYouTubeQuery *self = GDATA_YOUTUBE_QUERY (object);
434 
435 	switch (property_id) {
436 		case PROP_FORMAT:
437 			G_GNUC_BEGIN_IGNORE_DEPRECATIONS
438 			gdata_youtube_query_set_format (self, g_value_get_enum (value));
439 			G_GNUC_END_IGNORE_DEPRECATIONS
440 			break;
441 		case PROP_LATITUDE:
442 			self->priv->latitude = g_value_get_double (value);
443 			break;
444 		case PROP_LONGITUDE:
445 			self->priv->longitude = g_value_get_double (value);
446 			break;
447 		case PROP_LOCATION_RADIUS:
448 			self->priv->location_radius = g_value_get_double (value);
449 			break;
450 		case PROP_HAS_LOCATION:
451 			self->priv->has_location = g_value_get_boolean (value);
452 			break;
453 		case PROP_LANGUAGE:
454 			G_GNUC_BEGIN_IGNORE_DEPRECATIONS
455 			gdata_youtube_query_set_language (self, g_value_get_string (value));
456 			G_GNUC_END_IGNORE_DEPRECATIONS
457 			break;
458 		case PROP_ORDER_BY:
459 			gdata_youtube_query_set_order_by (self, g_value_get_string (value));
460 			break;
461 		case PROP_RESTRICTION:
462 			gdata_youtube_query_set_restriction (self, g_value_get_string (value));
463 			break;
464 		case PROP_SAFE_SEARCH:
465 			gdata_youtube_query_set_safe_search (self, g_value_get_enum (value));
466 			break;
467 		case PROP_SORT_ORDER:
468 			G_GNUC_BEGIN_IGNORE_DEPRECATIONS
469 			gdata_youtube_query_set_sort_order (self, g_value_get_enum (value));
470 			G_GNUC_END_IGNORE_DEPRECATIONS
471 			break;
472 		case PROP_AGE:
473 			gdata_youtube_query_set_age (self, g_value_get_enum (value));
474 			break;
475 		case PROP_UPLOADER:
476 			G_GNUC_BEGIN_IGNORE_DEPRECATIONS
477 			gdata_youtube_query_set_uploader (self, g_value_get_enum (value));
478 			G_GNUC_END_IGNORE_DEPRECATIONS
479 			break;
480 		case PROP_LICENSE:
481 			gdata_youtube_query_set_license (self, g_value_get_string (value));
482 			break;
483 		default:
484 			/* We don't have any other property... */
485 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
486 			break;
487 	}
488 }
489 
490 /* Convert from a v2 order-by parameter value to a v3 order parameter value.
491  * Reference:
492  * v2: https://developers.google.com/youtube/2.0/developers_guide_protocol_api_query_parameters#orderbysp
493  * v3: https://developers.google.com/youtube/v3/docs/search/list#order
494  */
495 static const gchar *
get_v3_order(const gchar * v2_order_by)496 get_v3_order (const gchar *v2_order_by)
497 {
498 	const struct {
499 		const gchar *v2_order_by;
500 		const gchar *v3_order;
501 	} mapping[] = {
502 		{ "relevance", "relevance" },
503 		{ "published", "date" },
504 		{ "viewCount", "viewCount" },
505 		{ "rating", "rating" },
506 	};
507 	guint i;
508 
509 	for (i = 0; i < G_N_ELEMENTS (mapping); i++) {
510 		if (g_strcmp0 (v2_order_by, mapping[i].v2_order_by) == 0) {
511 			return mapping[i].v3_order;
512 		}
513 	}
514 
515 	/* Special case for ‘relevance_lang_*’. */
516 	if (g_str_has_prefix (v2_order_by, "relevance_lang_")) {
517 		return "relevance";
518 	}
519 
520 	return NULL;
521 }
522 
523 /* Convert from a v2 license parameter value to a v3 videoLicense parameter
524  * value. Reference:
525  * v2: https://developers.google.com/youtube/2.0/developers_guide_protocol_api_query_parameters#licensesp
526  * v3: https://developers.google.com/youtube/v3/docs/search/list#videoLicense
527  */
528 static const gchar *
get_v3_video_license(const gchar * v2_license)529 get_v3_video_license (const gchar *v2_license)
530 {
531 	if (g_strcmp0 (v2_license, "cc") == 0) {
532 		return "creativeCommon";
533 	} else if (g_strcmp0 (v2_license, "youtube") == 0) {
534 		return "youtube";
535 	} else {
536 		return NULL;
537 	}
538 }
539 
540 static void
get_query_uri(GDataQuery * self,const gchar * feed_uri,GString * query_uri,gboolean * params_started)541 get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started)
542 {
543 	GDataYouTubeQueryPrivate *priv = GDATA_YOUTUBE_QUERY (self)->priv;
544 
545 	#define APPEND_SEP g_string_append_c (query_uri, (*params_started == FALSE) ? '?' : '&'); *params_started = TRUE;
546 
547 	/* NOTE: We do not chain up because the parent class implements a lot
548 	 * of deprecated API. */
549 
550 	/* Categories */
551 	if (gdata_query_get_categories (self) != NULL) {
552 		APPEND_SEP
553 		g_string_append (query_uri, "videoCategoryId=");
554 		g_string_append_uri_escaped (query_uri,
555 		                             gdata_query_get_categories (self),
556 		                             NULL,
557 		                             FALSE);
558 	}
559 
560 	/* q param */
561 	if (gdata_query_get_q (self) != NULL) {
562 		APPEND_SEP
563 		g_string_append (query_uri, "q=");
564 		g_string_append_uri_escaped (query_uri,
565 		                             gdata_query_get_q (self), NULL,
566 		                             FALSE);
567 	}
568 
569 	if (gdata_query_get_max_results (self) > 0) {
570 		APPEND_SEP
571 		g_string_append_printf (query_uri, "maxResults=%u",
572 		                        gdata_query_get_max_results (self));
573 	}
574 
575 	if (priv->age != GDATA_YOUTUBE_AGE_ALL_TIME) {
576 		gchar *after;
577 		GTimeVal tv = { 0, };
578 
579 		g_get_current_time (&tv);
580 
581 		/* Squash the microseconds; they’re not useful. */
582 		tv.tv_usec = 0;
583 
584 		switch (priv->age) {
585 		case GDATA_YOUTUBE_AGE_TODAY:
586 			tv.tv_sec -= 24 * 60 * 60;
587 			break;
588 		case GDATA_YOUTUBE_AGE_THIS_WEEK:
589 			tv.tv_sec -= 7 * 24 * 60 * 60;
590 			break;
591 		case GDATA_YOUTUBE_AGE_THIS_MONTH:
592 			tv.tv_sec -= 31 * 24 * 60 * 60;
593 			break;
594 		case GDATA_YOUTUBE_AGE_ALL_TIME:
595 		default:
596 			g_assert_not_reached ();
597 		}
598 
599 		APPEND_SEP
600 
601 		after = g_time_val_to_iso8601 (&tv);
602 		g_string_append_printf (query_uri, "publishedAfter=%s", after);
603 		g_free (after);
604 	}
605 
606 	/* We don’t need to use APPEND_SEP below here, as this parameter is
607 	 * always included */
608 	APPEND_SEP
609 	switch (priv->safe_search) {
610 		case GDATA_YOUTUBE_SAFE_SEARCH_NONE:
611 			g_string_append (query_uri, "safeSearch=none");
612 			break;
613 		case GDATA_YOUTUBE_SAFE_SEARCH_MODERATE:
614 			g_string_append (query_uri, "safeSearch=moderate");
615 			break;
616 		case GDATA_YOUTUBE_SAFE_SEARCH_STRICT:
617 			g_string_append (query_uri, "safeSearch=strict");
618 			break;
619 		default:
620 			g_assert_not_reached ();
621 	}
622 
623 	if (priv->latitude >= -90.0 && priv->latitude <= 90.0 &&
624 	    priv->longitude >= -180.0 && priv->longitude <= 180.0) {
625 		gchar latitude[G_ASCII_DTOSTR_BUF_SIZE];
626 		gchar longitude[G_ASCII_DTOSTR_BUF_SIZE];
627 
628 		g_string_append_printf (query_uri, "&location=%s,%s",
629 		                        g_ascii_dtostr (latitude,
630 		                                        sizeof (latitude),
631 		                                        priv->latitude),
632 		                        g_ascii_dtostr (longitude,
633 		                                        sizeof (longitude),
634 		                                        priv->longitude));
635 
636 		if (priv->location_radius >= 0.0) {
637 			gchar radius[G_ASCII_DTOSTR_BUF_SIZE];
638 			g_string_append_printf (query_uri, "&locationRadius=%sm",
639 			                        g_ascii_dtostr (radius,
640 			                                        sizeof (radius),
641 			                                        priv->location_radius));
642 		}
643 	}
644 
645 	if (priv->order_by != NULL) {
646 		const gchar *v3_order_by = get_v3_order (priv->order_by);
647 
648 		if (v3_order_by != NULL) {
649 			g_string_append (query_uri, "&order=");
650 			g_string_append_uri_escaped (query_uri, v3_order_by,
651 			                             NULL, FALSE);
652 		}
653 	}
654 
655 	if (priv->restriction != NULL) {
656 		g_string_append (query_uri, "&regionCode=");
657 		g_string_append_uri_escaped (query_uri, priv->restriction, NULL, FALSE);
658 	}
659 
660 	if (priv->license != NULL) {
661 		const gchar *v3_video_license;
662 
663 		v3_video_license = get_v3_video_license (priv->license);
664 
665 		if (v3_video_license != NULL) {
666 			g_string_append (query_uri, "&videoLicense=");
667 			g_string_append_uri_escaped (query_uri,
668 			                             v3_video_license, NULL,
669 			                             FALSE);
670 		}
671 	}
672 }
673 
674 /**
675  * gdata_youtube_query_new:
676  * @q: (allow-none): a query string, or %NULL
677  *
678  * Creates a new #GDataYouTubeQuery with its #GDataQuery:q property set to @q.
679  *
680  * Return value: a new #GDataYouTubeQuery
681  *
682  * Since: 0.3.0
683  */
684 GDataYouTubeQuery *
gdata_youtube_query_new(const gchar * q)685 gdata_youtube_query_new (const gchar *q)
686 {
687 	return g_object_new (GDATA_TYPE_YOUTUBE_QUERY, "q", q, NULL);
688 }
689 
690 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
691 
692 /**
693  * gdata_youtube_query_get_format:
694  * @self: a #GDataYouTubeQuery
695  *
696  * Gets the #GDataYouTubeQuery:format property.
697  *
698  * Return value: the format property
699  *
700  * Since: 0.3.0
701  * Deprecated: 0.17.0: No longer supported by Google. The value of
702  *   this property will be unused in queries. There is no replacement.
703  */
704 GDataYouTubeFormat
gdata_youtube_query_get_format(GDataYouTubeQuery * self)705 gdata_youtube_query_get_format (GDataYouTubeQuery *self)
706 {
707 	g_return_val_if_fail (GDATA_IS_YOUTUBE_QUERY (self), GDATA_YOUTUBE_FORMAT_UNKNOWN);
708 	return self->priv->format;
709 }
710 
711 /**
712  * gdata_youtube_query_set_format:
713  * @self: a #GDataYouTubeQuery
714  * @format: the requested video format
715  *
716  * Sets the #GDataYouTubeQuery:format property of the #GDataYouTubeQuery to @format.
717  *
718  * Since: 0.3.0
719  * Deprecated: 0.17.0: No longer supported by Google. The value of
720  *   this property will be unused in queries. There is no replacement.
721  */
722 void
gdata_youtube_query_set_format(GDataYouTubeQuery * self,GDataYouTubeFormat format)723 gdata_youtube_query_set_format (GDataYouTubeQuery *self, GDataYouTubeFormat format)
724 {
725 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
726 	self->priv->format = format;
727 	g_object_notify (G_OBJECT (self), "format");
728 
729 	/* Our current ETag will no longer be relevant */
730 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
731 }
732 
733 G_GNUC_END_IGNORE_DEPRECATIONS
734 
735 /**
736  * gdata_youtube_query_get_location:
737  * @self: a #GDataYouTubeQuery
738  * @latitude: (out caller-allocates) (allow-none): a location in which to return the latitude, or %NULL
739  * @longitude: (out caller-allocates) (allow-none): a location in which to return the longitude, or %NULL
740  * @radius: (out caller-allocates) (allow-none): a location in which to return the location radius, or %NULL
741  * @has_location: (out caller-allocates) (allow-none): a location in which to return %TRUE if the query is searching for videos with a specific
742  * location, %FALSE otherwise, or %NULL
743  *
744  * Gets the location-based properties of the #GDataYouTubeQuery<!-- -->: #GDataYouTubeQuery:latitude, #GDataYouTubeQuery:longitude,
745  * #GDataYouTubeQuery:location-radius and #GDataYouTubeQuery:has-location.
746  *
747  * Since: 0.3.0
748  */
749 void
gdata_youtube_query_get_location(GDataYouTubeQuery * self,gdouble * latitude,gdouble * longitude,gdouble * radius,gboolean * has_location)750 gdata_youtube_query_get_location (GDataYouTubeQuery *self, gdouble *latitude, gdouble *longitude, gdouble *radius, gboolean *has_location)
751 {
752 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
753 
754 	if (latitude != NULL)
755 		*latitude = self->priv->latitude;
756 	if (longitude != NULL)
757 		*longitude = self->priv->longitude;
758 	if (radius != NULL)
759 		*radius = self->priv->location_radius;
760 	if (has_location != NULL)
761 		*has_location = self->priv->has_location;
762 }
763 
764 /**
765  * gdata_youtube_query_set_location:
766  * @self: a #GDataYouTubeQuery
767  * @latitude: the new latitude, or %G_MAXDOUBLE
768  * @longitude: the new longitude, or %G_MAXDOUBLE
769  * @radius: the new location radius, or <code class="literal">0</code>
770  * @has_location: %TRUE if the query is for videos with a specific location, %FALSE otherwise
771  *
772  * Sets the location-based properties of the #GDataYouTubeQuery<!-- -->: #GDataYouTubeQuery:latitude, #GDataYouTubeQuery:longitude,
773  * #GDataYouTubeQuery:location-radius and #GDataYouTubeQuery:has-location.
774  *
775  * Since: 0.3.0
776  */
777 void
gdata_youtube_query_set_location(GDataYouTubeQuery * self,gdouble latitude,gdouble longitude,gdouble radius,gboolean has_location)778 gdata_youtube_query_set_location (GDataYouTubeQuery *self, gdouble latitude, gdouble longitude, gdouble radius, gboolean has_location)
779 {
780 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
781 
782 	self->priv->latitude = latitude;
783 	self->priv->longitude = longitude;
784 	self->priv->location_radius = radius;
785 	self->priv->has_location = has_location;
786 
787 	g_object_freeze_notify (G_OBJECT (self));
788 	g_object_notify (G_OBJECT (self), "latitude");
789 	g_object_notify (G_OBJECT (self), "longitude");
790 	g_object_notify (G_OBJECT (self), "location-radius");
791 	g_object_notify (G_OBJECT (self), "has-location");
792 	g_object_thaw_notify (G_OBJECT (self));
793 
794 	/* Our current ETag will no longer be relevant */
795 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
796 }
797 
798 /**
799  * gdata_youtube_query_get_language:
800  * @self: a #GDataYouTubeQuery
801  *
802  * Gets the #GDataYouTubeQuery:language property.
803  *
804  * Return value: the language property, or %NULL if it is unset
805  *
806  * Since: 0.3.0
807  * Deprecated: 0.17.0: No longer supported by Google. The value of
808  *   this property will be unused in queries. There is no replacement.
809  */
810 const gchar *
gdata_youtube_query_get_language(GDataYouTubeQuery * self)811 gdata_youtube_query_get_language (GDataYouTubeQuery *self)
812 {
813 	g_return_val_if_fail (GDATA_IS_YOUTUBE_QUERY (self), NULL);
814 	return self->priv->language;
815 }
816 
817 /**
818  * gdata_youtube_query_set_language:
819  * @self: a #GDataYouTubeQuery
820  * @language: (allow-none): a new language name, or %NULL
821  *
822  * Sets the #GDataYouTubeQuery:language property of the #GDataYouTubeQuery to the new language, @language.
823  *
824  * Set @language to %NULL to unset the property in the query URI.
825  *
826  * Since: 0.3.0
827  * Deprecated: 0.17.0: No longer supported by Google. The value of
828  *   this property will be unused in queries. There is no replacement.
829  */
830 void
gdata_youtube_query_set_language(GDataYouTubeQuery * self,const gchar * language)831 gdata_youtube_query_set_language (GDataYouTubeQuery *self, const gchar *language)
832 {
833 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
834 	g_free (self->priv->language);
835 	self->priv->language = g_strdup (language);
836 	g_object_notify (G_OBJECT (self), "language");
837 
838 	/* Our current ETag will no longer be relevant */
839 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
840 }
841 
842 /**
843  * gdata_youtube_query_get_order_by:
844  * @self: a #GDataYouTubeQuery
845  *
846  * Gets the #GDataYouTubeQuery:order-by property.
847  *
848  * Return value: the order by property, or %NULL if it is unset
849  *
850  * Since: 0.3.0
851  */
852 const gchar *
gdata_youtube_query_get_order_by(GDataYouTubeQuery * self)853 gdata_youtube_query_get_order_by (GDataYouTubeQuery *self)
854 {
855 	g_return_val_if_fail (GDATA_IS_YOUTUBE_QUERY (self), NULL);
856 	return self->priv->order_by;
857 }
858 
859 /**
860  * gdata_youtube_query_set_order_by:
861  * @self: a #GDataYouTubeQuery
862  * @order_by: (allow-none): a new order by string, or %NULL
863  *
864  * Sets the #GDataYouTubeQuery:order-by property of the #GDataYouTubeQuery to the new order by string, @order_by.
865  *
866  * Set @order_by to %NULL to unset the property in the query URI.
867  *
868  * Since: 0.3.0
869  */
870 void
gdata_youtube_query_set_order_by(GDataYouTubeQuery * self,const gchar * order_by)871 gdata_youtube_query_set_order_by (GDataYouTubeQuery *self, const gchar *order_by)
872 {
873 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
874 
875 	g_free (self->priv->order_by);
876 	self->priv->order_by = g_strdup (order_by);
877 	g_object_notify (G_OBJECT (self), "order-by");
878 
879 	/* Our current ETag will no longer be relevant */
880 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
881 }
882 
883 /**
884  * gdata_youtube_query_get_restriction:
885  * @self: a #GDataYouTubeQuery
886  *
887  * Gets the #GDataYouTubeQuery:restriction property.
888  *
889  * Return value: the restriction property, or %NULL if it is unset
890  *
891  * Since: 0.3.0
892  */
893 const gchar *
gdata_youtube_query_get_restriction(GDataYouTubeQuery * self)894 gdata_youtube_query_get_restriction (GDataYouTubeQuery *self)
895 {
896 	g_return_val_if_fail (GDATA_IS_YOUTUBE_QUERY (self), NULL);
897 	return self->priv->restriction;
898 }
899 
900 /**
901  * gdata_youtube_query_set_restriction:
902  * @self: a #GDataYouTubeQuery
903  * @restriction: (allow-none): a new restriction string, or %NULL
904  *
905  * Sets the #GDataYouTubeQuery:restriction property of the #GDataYouTubeQuery to the new restriction string, @restriction.
906  *
907  * Set @restriction to %NULL to unset the property in the query URI.
908  *
909  * Since: 0.3.0
910  */
911 void
gdata_youtube_query_set_restriction(GDataYouTubeQuery * self,const gchar * restriction)912 gdata_youtube_query_set_restriction (GDataYouTubeQuery *self, const gchar *restriction)
913 {
914 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
915 	g_free (self->priv->restriction);
916 	self->priv->restriction = g_strdup (restriction);
917 	g_object_notify (G_OBJECT (self), "restriction");
918 
919 	/* Our current ETag will no longer be relevant */
920 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
921 }
922 
923 /**
924  * gdata_youtube_query_get_safe_search:
925  * @self: a #GDataYouTubeQuery
926  *
927  * Gets the #GDataYouTubeQuery:safe-search property.
928  *
929  * Return value: the safe search property
930  *
931  * Since: 0.3.0
932  */
933 GDataYouTubeSafeSearch
gdata_youtube_query_get_safe_search(GDataYouTubeQuery * self)934 gdata_youtube_query_get_safe_search (GDataYouTubeQuery *self)
935 {
936 	g_return_val_if_fail (GDATA_IS_YOUTUBE_QUERY (self), GDATA_YOUTUBE_SAFE_SEARCH_MODERATE);
937 	return self->priv->safe_search;
938 }
939 
940 /**
941  * gdata_youtube_query_set_safe_search:
942  * @self: a #GDataYouTubeQuery
943  * @safe_search: a new safe search level
944  *
945  * Sets the #GDataYouTubeQuery:safe-search property of the #GDataYouTubeQuery to @safe_search.
946  *
947  * Since: 0.3.0
948  */
949 void
gdata_youtube_query_set_safe_search(GDataYouTubeQuery * self,GDataYouTubeSafeSearch safe_search)950 gdata_youtube_query_set_safe_search (GDataYouTubeQuery *self, GDataYouTubeSafeSearch safe_search)
951 {
952 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
953 	self->priv->safe_search = safe_search;
954 	g_object_notify (G_OBJECT (self), "safe-search");
955 
956 	/* Our current ETag will no longer be relevant */
957 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
958 }
959 
960 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
961 
962 /**
963  * gdata_youtube_query_get_sort_order:
964  * @self: a #GDataYouTubeQuery
965  *
966  * Gets the #GDataYouTubeQuery:sort-order property.
967  *
968  * Return value: the sort order property
969  *
970  * Since: 0.3.0
971  * Deprecated: 0.17.0: No longer supported by Google. The value of
972  *   this property will be unused in queries. There is no replacement.
973  */
974 GDataYouTubeSortOrder
gdata_youtube_query_get_sort_order(GDataYouTubeQuery * self)975 gdata_youtube_query_get_sort_order (GDataYouTubeQuery *self)
976 {
977 	g_return_val_if_fail (GDATA_IS_YOUTUBE_QUERY (self), GDATA_YOUTUBE_SORT_NONE);
978 	return self->priv->sort_order;
979 }
980 
981 /**
982  * gdata_youtube_query_set_sort_order:
983  * @self: a #GDataYouTubeQuery
984  * @sort_order: the new sort order
985  *
986  * Sets the #GDataYouTubeQuery:sort-order property of the #GDataYouTubeQuery to @sort_order.
987  *
988  * Set @sort_order to %GDATA_YOUTUBE_SORT_NONE to unset the property in the query URI.
989  *
990  * Since: 0.3.0
991  * Deprecated: 0.17.0: No longer supported by Google. The value of
992  *   this property will be unused in queries. There is no replacement.
993  */
994 void
gdata_youtube_query_set_sort_order(GDataYouTubeQuery * self,GDataYouTubeSortOrder sort_order)995 gdata_youtube_query_set_sort_order (GDataYouTubeQuery *self, GDataYouTubeSortOrder sort_order)
996 {
997 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
998 	self->priv->sort_order = sort_order;
999 	g_object_notify (G_OBJECT (self), "sort-order");
1000 
1001 	/* Our current ETag will no longer be relevant */
1002 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
1003 }
1004 
1005 G_GNUC_END_IGNORE_DEPRECATIONS
1006 
1007 /**
1008  * gdata_youtube_query_get_age:
1009  * @self: a #GDataYouTubeQuery
1010  *
1011  * Gets the #GDataYouTubeQuery:age property.
1012  *
1013  * Return value: the age property
1014  *
1015  * Since: 0.3.0
1016  */
1017 GDataYouTubeAge
gdata_youtube_query_get_age(GDataYouTubeQuery * self)1018 gdata_youtube_query_get_age (GDataYouTubeQuery *self)
1019 {
1020 	g_return_val_if_fail (GDATA_IS_YOUTUBE_QUERY (self), GDATA_YOUTUBE_AGE_ALL_TIME);
1021 	return self->priv->age;
1022 }
1023 
1024 /**
1025  * gdata_youtube_query_set_age:
1026  * @self: a #GDataYouTubeQuery
1027  * @age: the new age
1028  *
1029  * Sets the #GDataYouTubeQuery:age property of the #GDataYouTubeQuery to @age.
1030  *
1031  * Since: 0.3.0
1032  */
1033 void
gdata_youtube_query_set_age(GDataYouTubeQuery * self,GDataYouTubeAge age)1034 gdata_youtube_query_set_age (GDataYouTubeQuery *self, GDataYouTubeAge age)
1035 {
1036 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
1037 	self->priv->age = age;
1038 	g_object_notify (G_OBJECT (self), "age");
1039 
1040 	/* Our current ETag will no longer be relevant */
1041 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
1042 }
1043 
1044 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1045 
1046 /**
1047  * gdata_youtube_query_get_uploader:
1048  * @self: a #GDataYouTubeQuery
1049  *
1050  * Gets the #GDataYouTubeQuery:uploader property.
1051  *
1052  * Return value: the uploader property
1053  *
1054  * Since: 0.3.0
1055  * Deprecated: 0.17.0: No longer supported by Google. The value of
1056  *   this property will be unused in queries. There is no replacement.
1057  */
1058 GDataYouTubeUploader
gdata_youtube_query_get_uploader(GDataYouTubeQuery * self)1059 gdata_youtube_query_get_uploader (GDataYouTubeQuery *self)
1060 {
1061 	g_return_val_if_fail (GDATA_IS_YOUTUBE_QUERY (self), GDATA_YOUTUBE_UPLOADER_ALL);
1062 	return self->priv->uploader;
1063 }
1064 
1065 /**
1066  * gdata_youtube_query_set_uploader:
1067  * @self: a #GDataYouTubeQuery
1068  * @uploader: the new uploader
1069  *
1070  * Sets the #GDataYouTubeQuery:uploader property of the #GDataYouTubeQuery to @uploader.
1071  *
1072  * Since: 0.3.0
1073  * Deprecated: 0.17.0: No longer supported by Google. The value of
1074  *   this property will be unused in queries. There is no replacement.
1075  */
1076 void
gdata_youtube_query_set_uploader(GDataYouTubeQuery * self,GDataYouTubeUploader uploader)1077 gdata_youtube_query_set_uploader (GDataYouTubeQuery *self, GDataYouTubeUploader uploader)
1078 {
1079 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
1080 	self->priv->uploader = uploader;
1081 	g_object_notify (G_OBJECT (self), "uploader");
1082 
1083 	/* Our current ETag will no longer be relevant */
1084 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
1085 }
1086 
1087 G_GNUC_END_IGNORE_DEPRECATIONS
1088 
1089 /**
1090  * gdata_youtube_query_get_license:
1091  * @self: a #GDataYouTubeQuery
1092  *
1093  * Gets the #GDataYouTubeQuery:license property.
1094  *
1095  * Return value: the license property, or %NULL if it is unset
1096  *
1097  * Since: 0.11.0
1098  */
1099 const gchar *
gdata_youtube_query_get_license(GDataYouTubeQuery * self)1100 gdata_youtube_query_get_license (GDataYouTubeQuery *self)
1101 {
1102 	g_return_val_if_fail (GDATA_IS_YOUTUBE_QUERY (self), NULL);
1103 	return self->priv->license;
1104 }
1105 
1106 /**
1107  * gdata_youtube_query_set_license:
1108  * @self: a #GDataYouTubeQuery
1109  * @license: (allow-none): a new license value, or %NULL
1110  *
1111  * Sets the #GDataYouTubeQuery:license property of the #GDataYouTubeQuery to the new license value, @license.
1112  *
1113  * Set @license to %NULL to unset the property in the query URI.
1114  *
1115  * Since: 0.11.0
1116  */
1117 void
gdata_youtube_query_set_license(GDataYouTubeQuery * self,const gchar * license)1118 gdata_youtube_query_set_license (GDataYouTubeQuery *self, const gchar *license)
1119 {
1120 	g_return_if_fail (GDATA_IS_YOUTUBE_QUERY (self));
1121 	g_free (self->priv->license);
1122 	self->priv->license = g_strdup (license);
1123 	g_object_notify (G_OBJECT (self), "license");
1124 
1125 	/* Our current ETag will no longer be relevant */
1126 	gdata_query_set_etag (GDATA_QUERY (self), NULL);
1127 }
1128