--version: Add QUVI_VERSION_SCRIPTS_CONFIGURATION to output
[quvi-tool.git] / src / print / json_print.c
blob6df652b607cb6a838ab1846fcb6c3e02575f605d
1 /* quvi
2 * Copyright (C) 2012,2013 Toni Gundogdu <legatvs@gmail.com>
4 * This file is part of quvi <http://quvi.sourceforge.net/>.
6 * This program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU Affero General Public
8 * License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
11 * This program 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
14 * GNU Affero General Public License for more details.
16 * You should have received a copy of the GNU Affero General
17 * Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
21 /* "json" module buffers the data to an instance of JsonBuilder. */
23 #include "config.h"
25 #include <stdlib.h>
26 #include <json-glib/json-glib.h>
27 #include <glib/gprintf.h>
28 #include <quvi.h>
30 #if JSON_MAJOR_VERSION >=0 && JSON_MINOR_VERSION >=14
31 #define HAVE_PRETTY 1
32 #endif
34 #include "lutil.h"
35 /* -- */
36 #include "lprint.h"
38 struct json_s
40 quvi_media_t qm;
41 JsonBuilder *b;
42 quvi_t q;
45 typedef struct json_s *json_t;
47 static gint _json_handle_new(quvi_t q, quvi_media_t qm, gpointer *dst)
49 json_t p;
51 g_assert(dst != NULL);
53 p = g_new0(struct json_s, 1);
54 p->b = json_builder_new();
55 p->qm = qm;
56 p->q = q;
58 *dst = p;
60 return ((p->b != NULL) ? EXIT_SUCCESS:EXIT_FAILURE);
63 static gint _json_handle_free(gpointer data, const gint r)
65 json_t p = (json_t) data;
67 if (p == NULL)
68 return (r);
70 if (p->b != NULL)
72 g_object_unref(p->b);
73 p->b = NULL;
75 g_free(p);
77 return (r);
80 static gint _print_buffer(const json_t p)
82 JsonGenerator *g;
83 JsonNode *r;
84 gchar *s;
86 g_assert(p != NULL);
88 g = json_generator_new();
89 r = json_builder_get_root(p->b);
91 json_generator_set_root(g, r);
92 #ifdef HAVE_PRETTY
93 json_generator_set_pretty(g, 1);
94 #endif
95 s = json_generator_to_data(g, NULL);
97 json_node_free(r);
98 g_object_unref(g);
100 g_print("%s\n", s);
101 g_free(s);
103 return (EXIT_SUCCESS);
106 void lprint_json_errmsg(const gchar *fmt, ...)
108 va_list args;
109 gchar *s;
111 va_start(args, fmt);
112 if (g_vasprintf(&s, fmt, args) >0)
114 gchar *e = g_uri_escape_string(s, NULL, TRUE);
115 g_printerr("{\"error\" : \"%s\"}\n", e);
116 g_free(e);
117 g_free(s);
119 va_end(args);
122 typedef lprint_cb_errmsg cem;
124 /* media */
126 gint lprint_json_media_new(quvi_t q, quvi_media_t qm, gpointer *dst)
128 return (_json_handle_new(q, qm, dst));
131 void lprint_json_media_free(gpointer data)
133 _json_handle_free(data, -1);
136 gint lprint_json_media_print_buffer(gpointer data)
138 json_t p = (json_t) data;
140 g_assert(data != NULL);
141 g_assert(p->b != NULL);
143 json_builder_end_object(p->b); /* media */
144 json_builder_end_object(p->b); /* quvi */
145 json_builder_end_object(p->b); /* root */
147 return (_print_buffer(p));
150 static gint _set_member(const json_t p, const lutilPropertyType pt,
151 const gchar *n, const gchar *s, const gdouble d)
153 const gint r = lutil_chk_property_ok(p->q, pt, n, lprint_json_errmsg);
155 if (r != EXIT_SUCCESS)
156 return (EXIT_FAILURE);
158 json_builder_set_member_name(p->b, n);
159 if (s != NULL)
161 gchar *e = g_uri_escape_string(s, NULL, TRUE);
162 json_builder_add_string_value(p->b, e);
163 g_free(e);
165 else
166 json_builder_add_double_value(p->b, d);
168 return (EXIT_SUCCESS);
171 static gint _mp_s(const json_t p, const QuviMediaProperty qmp, const gchar *n)
173 gchar *s = NULL;
174 quvi_media_get(p->qm, qmp, &s);
175 return (_set_member(p, UTIL_PROPERTY_TYPE_MEDIA, n, s, -1));
178 #define _print_mp_s(n)\
179 do {\
180 if (_mp_s(p, n, #n) != EXIT_SUCCESS)\
181 return (EXIT_FAILURE);\
182 } while (0)
184 static gint _mp_d(const json_t p, const QuviMediaProperty qmp, const gchar *n)
186 gdouble d = 0;
187 quvi_media_get(p->qm, qmp, &d);
188 return (_set_member(p, UTIL_PROPERTY_TYPE_MEDIA, n, NULL, d));
191 #define _print_mp_d(n)\
192 do {\
193 if (_mp_d(p, n, #n) != EXIT_SUCCESS)\
194 return (EXIT_FAILURE);\
195 } while (0)
197 static gint _mi_s(const json_t p, const quvi_http_metainfo_t qmi,
198 const QuviHTTPMetaInfoProperty qmip, const gchar *n)
200 gchar *s = NULL;
201 quvi_http_metainfo_get(qmi, qmip, &s);
202 return (_set_member(p, UTIL_PROPERTY_TYPE_HTTP_METAINFO, n, s, -1));
205 #define _print_mi_s(n)\
206 do {\
207 if (_mi_s(p, qmi, n, #n) != EXIT_SUCCESS)\
208 return (EXIT_FAILURE);\
209 } while (0)
211 static gint _mi_d(const json_t p, const quvi_http_metainfo_t qmi,
212 const QuviHTTPMetaInfoProperty qmip, const gchar *n)
214 gdouble d = 0;
215 quvi_http_metainfo_get(qmi, qmip, &d);
216 return (_set_member(p, UTIL_PROPERTY_TYPE_HTTP_METAINFO, n, NULL, d));
219 #define _print_mi_d(n)\
220 do {\
221 if (_mi_d(p, qmi, n, #n) != EXIT_SUCCESS)\
222 return (EXIT_FAILURE);\
223 } while (0)
225 static gint
226 _print_media_stream_properties(const json_t p, const quvi_http_metainfo_t qmi)
228 json_builder_begin_object(p->b);
230 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_VIDEO_ENCODING);
231 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_AUDIO_ENCODING);
232 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_CONTAINER);
233 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_URL);
234 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_ID);
236 _print_mp_d(QUVI_MEDIA_STREAM_PROPERTY_VIDEO_BITRATE_KBIT_S);
237 _print_mp_d(QUVI_MEDIA_STREAM_PROPERTY_AUDIO_BITRATE_KBIT_S);
238 _print_mp_d(QUVI_MEDIA_STREAM_PROPERTY_VIDEO_HEIGHT);
239 _print_mp_d(QUVI_MEDIA_STREAM_PROPERTY_VIDEO_WIDTH);
241 if (qmi != NULL)
243 _print_mi_s(QUVI_HTTP_METAINFO_PROPERTY_FILE_EXTENSION);
244 _print_mi_s(QUVI_HTTP_METAINFO_PROPERTY_CONTENT_TYPE);
245 _print_mi_d(QUVI_HTTP_METAINFO_PROPERTY_LENGTH_BYTES);
248 json_builder_end_object(p->b); /* stream */
249 return (EXIT_SUCCESS);
252 gint
253 lprint_json_media_stream_properties(quvi_http_metainfo_t qmi, gpointer data)
255 json_t p = (json_t) data;
257 g_assert(data != NULL);
258 g_assert(p->b != NULL);
260 json_builder_set_member_name(p->b, "stream");
261 return (_print_media_stream_properties(p, qmi));
264 gint lprint_json_media_streams_available(quvi_t q, quvi_media_t qm)
266 json_t p;
267 gint r;
269 if (_json_handle_new(q, qm, (gpointer*) &p) != EXIT_SUCCESS)
270 return (EXIT_FAILURE);
272 json_builder_begin_object(p->b); /* root */
274 json_builder_set_member_name(p->b, "quvi");
275 json_builder_begin_object(p->b);
277 json_builder_set_member_name(p->b, "media");
278 json_builder_begin_object(p->b);
280 json_builder_set_member_name(p->b, "streams");
281 json_builder_begin_array(p->b);
283 r = EXIT_SUCCESS;
284 while (quvi_media_stream_next(qm) == QUVI_TRUE && r == EXIT_SUCCESS)
285 r = _print_media_stream_properties(p, NULL);
287 json_builder_end_array(p->b); /* streams */
288 json_builder_end_object(p->b); /* media */
289 json_builder_end_object(p->b); /* quvi */
290 json_builder_end_object(p->b); /* root */
292 if (r == EXIT_SUCCESS)
293 r = _print_buffer(p);
295 return (_json_handle_free(p, r));
298 #undef _print_mi_s
299 #undef _print_mi_d
301 gint lprint_json_media_properties(gpointer data)
303 json_t p = (json_t) data;
305 g_assert(data != NULL);
306 json_builder_begin_object(p->b); /* root */
308 json_builder_set_member_name(p->b, "quvi");
309 json_builder_begin_object(p->b);
311 json_builder_set_member_name(p->b, "media");
312 json_builder_begin_object(p->b);
314 _print_mp_s(QUVI_MEDIA_PROPERTY_THUMBNAIL_URL);
315 _print_mp_s(QUVI_MEDIA_PROPERTY_TITLE);
316 _print_mp_s(QUVI_MEDIA_PROPERTY_ID);
318 _print_mp_d(QUVI_MEDIA_PROPERTY_START_TIME_MS);
319 _print_mp_d(QUVI_MEDIA_PROPERTY_DURATION_MS);
321 return (EXIT_SUCCESS);
324 #undef _print_mp_s
325 #undef _print_mp_d
327 /* playlist */
329 gint lprint_json_playlist_new(quvi_t q, gpointer *dst)
331 return (_json_handle_new(q, NULL, dst));
334 void lprint_json_playlist_free(gpointer data)
336 _json_handle_free(data, -1);
339 gint lprint_json_playlist_print_buffer(gpointer data)
341 return (_print_buffer(data));
344 static gint _pp_s(const json_t p, const quvi_playlist_t qp,
345 const QuviPlaylistProperty qpp, const gchar *n)
347 gchar *s = NULL;
348 quvi_playlist_get(qp, qpp, &s);
349 return (_set_member(p, UTIL_PROPERTY_TYPE_PLAYLIST, n, s, -1));
352 #define _print_pp_s(n)\
353 do {\
354 if (_pp_s(p, qp, n, #n) != EXIT_SUCCESS)\
355 return (EXIT_FAILURE);\
356 } while (0)
358 static gint _pp_d(const json_t p, const quvi_playlist_t qp,
359 const QuviPlaylistProperty qpp, const gchar *n)
361 gdouble d = 0;
362 quvi_playlist_get(qp, qpp, &d);
363 return (_set_member(p, UTIL_PROPERTY_TYPE_PLAYLIST, n, NULL, d));
366 #define _print_pp_d(n)\
367 do {\
368 if (_pp_d(p, qp, n, #n) != EXIT_SUCCESS)\
369 return (EXIT_FAILURE);\
370 } while (0)
372 gint lprint_json_playlist_properties(quvi_playlist_t qp, gpointer data)
374 json_t p = (json_t) data;
376 g_assert(data != NULL);
377 g_assert(qp != NULL);
379 json_builder_begin_object(p->b); /* root */
381 json_builder_set_member_name(p->b, "quvi");
382 json_builder_begin_object(p->b);
384 json_builder_set_member_name(p->b, "playlist");
385 json_builder_begin_object(p->b);
387 _print_pp_s(QUVI_PLAYLIST_PROPERTY_THUMBNAIL_URL);
388 _print_pp_s(QUVI_PLAYLIST_PROPERTY_TITLE);
389 _print_pp_s(QUVI_PLAYLIST_PROPERTY_ID);
391 json_builder_set_member_name(p->b, "media");
392 json_builder_begin_array(p->b);
394 while (quvi_playlist_media_next(qp) == QUVI_TRUE)
396 json_builder_begin_object(p->b); /* media */
397 _print_pp_d(QUVI_PLAYLIST_MEDIA_PROPERTY_DURATION_MS);
398 _print_pp_s(QUVI_PLAYLIST_MEDIA_PROPERTY_TITLE);
399 _print_pp_s(QUVI_PLAYLIST_MEDIA_PROPERTY_URL);
400 json_builder_end_object(p->b); /* media */
403 json_builder_end_array(p->b); /* media */
404 json_builder_end_object(p->b); /* playlist */
406 json_builder_end_object(p->b); /* quvi */
407 json_builder_end_object(p->b); /* root */
409 return (EXIT_SUCCESS);
412 #undef _print_pp_s
413 #undef _print_pp_d
415 /* scan */
417 gint lprint_json_scan_new(quvi_t q, gpointer *dst)
419 return (_json_handle_new(q, NULL, dst));
422 void lprint_json_scan_free(gpointer data)
424 _json_handle_free(data, -1);
427 gint lprint_json_scan_print_buffer(gpointer data)
429 return (_print_buffer(data));
432 gint lprint_json_scan_properties(quvi_scan_t qs, gpointer data)
434 const gchar *s;
435 gchar *e;
436 json_t p;
438 g_assert(data != NULL);
439 g_assert(qs != NULL);
440 p = (json_t) data;
442 json_builder_begin_object(p->b); /* root */
444 json_builder_set_member_name(p->b, "quvi");
445 json_builder_begin_object(p->b);
447 json_builder_set_member_name(p->b, "scan");
448 json_builder_begin_object(p->b);
450 json_builder_set_member_name(p->b, "media");
451 json_builder_begin_array(p->b);
453 while ( (s = quvi_scan_next_media_url(qs)) != NULL)
455 json_builder_begin_object(p->b);
456 json_builder_set_member_name(p->b, "url");
458 e = g_uri_escape_string(s, NULL, TRUE);
459 json_builder_add_string_value(p->b, e);
461 json_builder_end_object(p->b);
462 g_free(e);
465 json_builder_end_array(p->b); /* media */
466 json_builder_end_object(p->b); /* scan */
468 json_builder_end_object(p->b); /* quvi */
469 json_builder_end_object(p->b); /* root */
471 return (EXIT_SUCCESS);
474 /* subtitle */
476 gint lprint_json_subtitle_new(quvi_t q, gpointer *dst)
478 return (_json_handle_new(q, NULL, dst));
481 void lprint_json_subtitle_free(gpointer data)
483 _json_handle_free(data, -1);
486 gint lprint_json_subtitle_print_buffer(gpointer data)
488 return (_print_buffer(data));
491 static gint _stp_d(const json_t p, const quvi_subtitle_type_t qst,
492 const QuviSubtitleTypeProperty qstp, const gchar *n)
494 gdouble d = 0;
495 quvi_subtitle_type_get(qst, qstp, &d);
496 return (_set_member(p, UTIL_PROPERTY_TYPE_SUBTITLE_LANGUAGE, n, NULL, d));
499 #define _print_stp_d(n)\
500 do {\
501 if (_stp_d(p, t, n, #n) != EXIT_SUCCESS)\
502 return (EXIT_FAILURE);\
503 } while (0)
505 static gint _slp_s(const json_t p, const quvi_subtitle_lang_t qsl,
506 const QuviSubtitleLangProperty qslp, const gchar *n)
508 gchar *s = NULL;
509 quvi_subtitle_lang_get(qsl, qslp, &s);
510 return (_set_member(p, UTIL_PROPERTY_TYPE_SUBTITLE_LANGUAGE, n, s, -1));
513 #define _print_slp_s(n)\
514 do {\
515 if (_slp_s(p, l, n, #n) != EXIT_SUCCESS)\
516 return (EXIT_FAILURE);\
517 } while (0)
519 static gint _append_lang_properties(const quvi_subtitle_lang_t l,
520 const json_t p)
522 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_TRANSLATED);
523 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_ORIGINAL);
524 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_CODE);
525 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_URL);
526 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_ID);
527 return (EXIT_SUCCESS);
530 gint
531 lprint_json_subtitle_lang_properties(quvi_subtitle_lang_t l, gpointer data)
533 json_t p;
534 gint r;
536 g_assert(data != NULL);
537 p = (json_t) data;
539 json_builder_begin_object(p->b); /* root */
541 json_builder_set_member_name(p->b, "quvi");
542 json_builder_begin_object(p->b);
544 json_builder_set_member_name(p->b, "media");
545 json_builder_begin_object(p->b);
547 json_builder_set_member_name(p->b, "subtitle");
548 json_builder_begin_object(p->b);
550 json_builder_set_member_name(p->b, "language");
551 json_builder_begin_object(p->b);
553 r = _append_lang_properties(l, p);
555 json_builder_end_object(p->b); /* language */
556 json_builder_end_object(p->b); /* subtitle */
558 json_builder_end_object(p->b); /* media */
559 json_builder_end_object(p->b); /* quvi */
560 json_builder_end_object(p->b); /* root */
562 return (r);
565 static gint _foreach_subtitle_lang(const json_t p,
566 const quvi_subtitle_type_t t)
568 quvi_subtitle_lang_t l;
569 gint r;
571 json_builder_set_member_name(p->b, "languages");
572 json_builder_begin_array(p->b);
574 r = EXIT_SUCCESS;
575 while ( (l = quvi_subtitle_lang_next(t)) != NULL && r ==EXIT_SUCCESS)
577 json_builder_begin_object(p->b);
578 r = _append_lang_properties(l, p);
579 json_builder_end_object(p->b);
581 json_builder_end_array(p->b); /* languages */
583 return (r);
586 gint lprint_json_subtitles_available(quvi_t q, quvi_subtitle_t qsub)
588 quvi_subtitle_type_t t;
589 json_t p;
590 gint r;
592 g_assert(qsub != NULL);
593 g_assert(q != NULL);
595 if (_json_handle_new(q, NULL, (gpointer*) &p) != EXIT_SUCCESS)
596 return (EXIT_FAILURE);
598 json_builder_begin_object(p->b); /* root */
600 json_builder_set_member_name(p->b, "quvi");
601 json_builder_begin_object(p->b);
603 json_builder_set_member_name(p->b, "media");
604 json_builder_begin_object(p->b);
606 json_builder_set_member_name(p->b, "subtitle");
607 json_builder_begin_object(p->b);
609 json_builder_set_member_name(p->b, "types");
610 json_builder_begin_array(p->b);
612 r = EXIT_SUCCESS;
613 while ( (t = quvi_subtitle_type_next(qsub)) != NULL && r ==EXIT_SUCCESS)
615 json_builder_begin_object(p->b);
616 _print_stp_d(QUVI_SUBTITLE_TYPE_PROPERTY_FORMAT);
617 _print_stp_d(QUVI_SUBTITLE_TYPE_PROPERTY_TYPE);
618 r = _foreach_subtitle_lang(p, t);
619 json_builder_end_object(p->b);
622 json_builder_end_array(p->b); /* types */
623 json_builder_end_object(p->b); /* subtitle */
625 json_builder_end_object(p->b); /* media */
626 json_builder_end_object(p->b); /* quvi */
627 json_builder_end_object(p->b); /* root */
629 if (r == EXIT_SUCCESS)
630 r = _print_buffer(p);
632 return (_json_handle_free(p, r));
635 #undef _print_slp_s
636 #undef _print_stp_d
638 /* vim: set ts=2 sw=2 tw=72 expandtab: */