Update NEWS for v0.9.5
[quvi-tool.git] / src / print / json_print.c
blobc62796f2cf4fd27089ea32cca69c19983505d371
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 extern const gchar *reserved_chars;
108 void lprint_json_errmsg(const gchar *fmt, ...)
110 va_list args;
111 gchar *s;
113 va_start(args, fmt);
114 if (g_vasprintf(&s, fmt, args) >0)
116 gchar *e = g_uri_escape_string(s, reserved_chars, FALSE);
117 g_printerr("{\"error\" : \"%s\"}\n", e);
118 g_free(e);
119 g_free(s);
121 va_end(args);
124 typedef lprint_cb_errmsg cem;
126 /* media */
128 gint lprint_json_media_new(quvi_t q, quvi_media_t qm, gpointer *dst)
130 return (_json_handle_new(q, qm, dst));
133 void lprint_json_media_free(gpointer data)
135 _json_handle_free(data, -1);
138 gint lprint_json_media_print_buffer(gpointer data)
140 json_t p = (json_t) data;
142 g_assert(data != NULL);
143 g_assert(p->b != NULL);
145 json_builder_end_object(p->b); /* media */
146 json_builder_end_object(p->b); /* quvi */
147 json_builder_end_object(p->b); /* root */
149 return (_print_buffer(p));
152 static gint _set_member(const json_t p, const lutilPropertyType pt,
153 const gchar *n, const gchar *s, const gdouble d)
155 const gint r = lutil_chk_property_ok(p->q, pt, n, lprint_json_errmsg);
157 if (r != EXIT_SUCCESS)
158 return (EXIT_FAILURE);
160 json_builder_set_member_name(p->b, n);
161 if (s != NULL)
163 gchar *e = g_uri_escape_string(s, reserved_chars, FALSE);
164 json_builder_add_string_value(p->b, e);
165 g_free(e);
167 else
168 json_builder_add_double_value(p->b, d);
170 return (EXIT_SUCCESS);
173 static gint _mp_s(const json_t p, const QuviMediaProperty qmp, const gchar *n)
175 gchar *s = NULL;
176 quvi_media_get(p->qm, qmp, &s);
177 return (_set_member(p, UTIL_PROPERTY_TYPE_MEDIA, n, s, -1));
180 #define _print_mp_s(n)\
181 do {\
182 if (_mp_s(p, n, #n) != EXIT_SUCCESS)\
183 return (EXIT_FAILURE);\
184 } while (0)
186 static gint _mp_d(const json_t p, const QuviMediaProperty qmp, const gchar *n)
188 gdouble d = 0;
189 quvi_media_get(p->qm, qmp, &d);
190 return (_set_member(p, UTIL_PROPERTY_TYPE_MEDIA, n, NULL, d));
193 #define _print_mp_d(n)\
194 do {\
195 if (_mp_d(p, n, #n) != EXIT_SUCCESS)\
196 return (EXIT_FAILURE);\
197 } while (0)
199 static gint _mi_s(const json_t p, const quvi_http_metainfo_t qmi,
200 const QuviHTTPMetaInfoProperty qmip, const gchar *n)
202 gchar *s = NULL;
203 quvi_http_metainfo_get(qmi, qmip, &s);
204 return (_set_member(p, UTIL_PROPERTY_TYPE_HTTP_METAINFO, n, s, -1));
207 #define _print_mi_s(n)\
208 do {\
209 if (_mi_s(p, qmi, n, #n) != EXIT_SUCCESS)\
210 return (EXIT_FAILURE);\
211 } while (0)
213 static gint _mi_d(const json_t p, const quvi_http_metainfo_t qmi,
214 const QuviHTTPMetaInfoProperty qmip, const gchar *n)
216 gdouble d = 0;
217 quvi_http_metainfo_get(qmi, qmip, &d);
218 return (_set_member(p, UTIL_PROPERTY_TYPE_HTTP_METAINFO, n, NULL, d));
221 #define _print_mi_d(n)\
222 do {\
223 if (_mi_d(p, qmi, n, #n) != EXIT_SUCCESS)\
224 return (EXIT_FAILURE);\
225 } while (0)
227 static gint
228 _print_media_stream_properties(const json_t p, const quvi_http_metainfo_t qmi)
230 json_builder_begin_object(p->b);
232 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_VIDEO_ENCODING);
233 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_AUDIO_ENCODING);
234 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_CONTAINER);
235 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_URL);
236 _print_mp_s(QUVI_MEDIA_STREAM_PROPERTY_ID);
238 _print_mp_d(QUVI_MEDIA_STREAM_PROPERTY_VIDEO_BITRATE_KBIT_S);
239 _print_mp_d(QUVI_MEDIA_STREAM_PROPERTY_AUDIO_BITRATE_KBIT_S);
240 _print_mp_d(QUVI_MEDIA_STREAM_PROPERTY_VIDEO_HEIGHT);
241 _print_mp_d(QUVI_MEDIA_STREAM_PROPERTY_VIDEO_WIDTH);
243 if (qmi != NULL)
245 _print_mi_s(QUVI_HTTP_METAINFO_PROPERTY_FILE_EXTENSION);
246 _print_mi_s(QUVI_HTTP_METAINFO_PROPERTY_CONTENT_TYPE);
247 _print_mi_d(QUVI_HTTP_METAINFO_PROPERTY_LENGTH_BYTES);
250 json_builder_end_object(p->b); /* stream */
251 return (EXIT_SUCCESS);
254 gint
255 lprint_json_media_stream_properties(quvi_http_metainfo_t qmi, gpointer data)
257 json_t p = (json_t) data;
259 g_assert(data != NULL);
260 g_assert(p->b != NULL);
262 json_builder_set_member_name(p->b, "stream");
263 return (_print_media_stream_properties(p, qmi));
266 gint lprint_json_media_streams_available(quvi_t q, quvi_media_t qm)
268 json_t p;
269 gint r;
271 if (_json_handle_new(q, qm, (gpointer*) &p) != EXIT_SUCCESS)
272 return (EXIT_FAILURE);
274 json_builder_begin_object(p->b); /* root */
276 json_builder_set_member_name(p->b, "quvi");
277 json_builder_begin_object(p->b);
279 json_builder_set_member_name(p->b, "media");
280 json_builder_begin_object(p->b);
282 json_builder_set_member_name(p->b, "streams");
283 json_builder_begin_array(p->b);
285 r = EXIT_SUCCESS;
286 while (quvi_media_stream_next(qm) == QUVI_TRUE && r == EXIT_SUCCESS)
287 r = _print_media_stream_properties(p, NULL);
289 json_builder_end_array(p->b); /* streams */
290 json_builder_end_object(p->b); /* media */
291 json_builder_end_object(p->b); /* quvi */
292 json_builder_end_object(p->b); /* root */
294 if (r == EXIT_SUCCESS)
295 r = _print_buffer(p);
297 return (_json_handle_free(p, r));
300 #undef _print_mi_s
301 #undef _print_mi_d
303 gint lprint_json_media_properties(gpointer data)
305 json_t p = (json_t) data;
307 g_assert(data != NULL);
308 json_builder_begin_object(p->b); /* root */
310 json_builder_set_member_name(p->b, "quvi");
311 json_builder_begin_object(p->b);
313 json_builder_set_member_name(p->b, "media");
314 json_builder_begin_object(p->b);
316 _print_mp_s(QUVI_MEDIA_PROPERTY_THUMBNAIL_URL);
317 _print_mp_s(QUVI_MEDIA_PROPERTY_TITLE);
318 _print_mp_s(QUVI_MEDIA_PROPERTY_ID);
320 _print_mp_d(QUVI_MEDIA_PROPERTY_START_TIME_MS);
321 _print_mp_d(QUVI_MEDIA_PROPERTY_DURATION_MS);
323 return (EXIT_SUCCESS);
326 #undef _print_mp_s
327 #undef _print_mp_d
329 /* playlist */
331 gint lprint_json_playlist_new(quvi_t q, gpointer *dst)
333 return (_json_handle_new(q, NULL, dst));
336 void lprint_json_playlist_free(gpointer data)
338 _json_handle_free(data, -1);
341 gint lprint_json_playlist_print_buffer(gpointer data)
343 return (_print_buffer(data));
346 static gint _pp_s(const json_t p, const quvi_playlist_t qp,
347 const QuviPlaylistProperty qpp, const gchar *n)
349 gchar *s = NULL;
350 quvi_playlist_get(qp, qpp, &s);
351 return (_set_member(p, UTIL_PROPERTY_TYPE_PLAYLIST, n, s, -1));
354 #define _print_pp_s(n)\
355 do {\
356 if (_pp_s(p, qp, n, #n) != EXIT_SUCCESS)\
357 return (EXIT_FAILURE);\
358 } while (0)
360 static gint _pp_d(const json_t p, const quvi_playlist_t qp,
361 const QuviPlaylistProperty qpp, const gchar *n)
363 gdouble d = 0;
364 quvi_playlist_get(qp, qpp, &d);
365 return (_set_member(p, UTIL_PROPERTY_TYPE_PLAYLIST, n, NULL, d));
368 #define _print_pp_d(n)\
369 do {\
370 if (_pp_d(p, qp, n, #n) != EXIT_SUCCESS)\
371 return (EXIT_FAILURE);\
372 } while (0)
374 gint lprint_json_playlist_properties(quvi_playlist_t qp, gpointer data)
376 json_t p = (json_t) data;
378 g_assert(data != NULL);
379 g_assert(qp != NULL);
381 json_builder_begin_object(p->b); /* root */
383 json_builder_set_member_name(p->b, "quvi");
384 json_builder_begin_object(p->b);
386 json_builder_set_member_name(p->b, "playlist");
387 json_builder_begin_object(p->b);
389 _print_pp_s(QUVI_PLAYLIST_PROPERTY_THUMBNAIL_URL);
390 _print_pp_s(QUVI_PLAYLIST_PROPERTY_TITLE);
391 _print_pp_s(QUVI_PLAYLIST_PROPERTY_ID);
393 json_builder_set_member_name(p->b, "media");
394 json_builder_begin_array(p->b);
396 while (quvi_playlist_media_next(qp) == QUVI_TRUE)
398 json_builder_begin_object(p->b); /* media */
399 _print_pp_d(QUVI_PLAYLIST_MEDIA_PROPERTY_DURATION_MS);
400 _print_pp_s(QUVI_PLAYLIST_MEDIA_PROPERTY_TITLE);
401 _print_pp_s(QUVI_PLAYLIST_MEDIA_PROPERTY_URL);
402 json_builder_end_object(p->b); /* media */
405 json_builder_end_array(p->b); /* media */
406 json_builder_end_object(p->b); /* playlist */
408 json_builder_end_object(p->b); /* quvi */
409 json_builder_end_object(p->b); /* root */
411 return (EXIT_SUCCESS);
414 #undef _print_pp_s
415 #undef _print_pp_d
417 /* scan */
419 gint lprint_json_scan_new(quvi_t q, gpointer *dst)
421 return (_json_handle_new(q, NULL, dst));
424 void lprint_json_scan_free(gpointer data)
426 _json_handle_free(data, -1);
429 gint lprint_json_scan_print_buffer(gpointer data)
431 return (_print_buffer(data));
434 gint lprint_json_scan_properties(quvi_scan_t qs, gpointer data)
436 const gchar *s;
437 gchar *e;
438 json_t p;
440 g_assert(data != NULL);
441 g_assert(qs != NULL);
442 p = (json_t) data;
444 json_builder_begin_object(p->b); /* root */
446 json_builder_set_member_name(p->b, "quvi");
447 json_builder_begin_object(p->b);
449 json_builder_set_member_name(p->b, "scan");
450 json_builder_begin_object(p->b);
452 json_builder_set_member_name(p->b, "media");
453 json_builder_begin_array(p->b);
455 while ( (s = quvi_scan_next_media_url(qs)) != NULL)
457 json_builder_begin_object(p->b);
458 json_builder_set_member_name(p->b, "url");
460 e = g_uri_escape_string(s, reserved_chars, FALSE);
461 json_builder_add_string_value(p->b, e);
463 json_builder_end_object(p->b);
464 g_free(e);
467 json_builder_end_array(p->b); /* media */
468 json_builder_end_object(p->b); /* scan */
470 json_builder_end_object(p->b); /* quvi */
471 json_builder_end_object(p->b); /* root */
473 return (EXIT_SUCCESS);
476 /* subtitle */
478 gint lprint_json_subtitle_new(quvi_t q, gpointer *dst)
480 return (_json_handle_new(q, NULL, dst));
483 void lprint_json_subtitle_free(gpointer data)
485 _json_handle_free(data, -1);
488 gint lprint_json_subtitle_print_buffer(gpointer data)
490 return (_print_buffer(data));
493 static gint _stp_d(const json_t p, const quvi_subtitle_type_t qst,
494 const QuviSubtitleTypeProperty qstp, const gchar *n)
496 gdouble d = 0;
497 quvi_subtitle_type_get(qst, qstp, &d);
498 return (_set_member(p, UTIL_PROPERTY_TYPE_SUBTITLE_LANGUAGE, n, NULL, d));
501 #define _print_stp_d(n)\
502 do {\
503 if (_stp_d(p, t, n, #n) != EXIT_SUCCESS)\
504 return (EXIT_FAILURE);\
505 } while (0)
507 static gint _slp_s(const json_t p, const quvi_subtitle_lang_t qsl,
508 const QuviSubtitleLangProperty qslp, const gchar *n)
510 gchar *s = NULL;
511 quvi_subtitle_lang_get(qsl, qslp, &s);
512 return (_set_member(p, UTIL_PROPERTY_TYPE_SUBTITLE_LANGUAGE, n, s, -1));
515 #define _print_slp_s(n)\
516 do {\
517 if (_slp_s(p, l, n, #n) != EXIT_SUCCESS)\
518 return (EXIT_FAILURE);\
519 } while (0)
521 static gint _append_lang_properties(const quvi_subtitle_lang_t l,
522 const json_t p)
524 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_TRANSLATED);
525 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_ORIGINAL);
526 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_CODE);
527 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_URL);
528 _print_slp_s(QUVI_SUBTITLE_LANG_PROPERTY_ID);
529 return (EXIT_SUCCESS);
532 gint
533 lprint_json_subtitle_lang_properties(quvi_subtitle_lang_t l, gpointer data)
535 json_t p;
536 gint r;
538 g_assert(data != NULL);
539 p = (json_t) data;
541 json_builder_begin_object(p->b); /* root */
543 json_builder_set_member_name(p->b, "quvi");
544 json_builder_begin_object(p->b);
546 json_builder_set_member_name(p->b, "media");
547 json_builder_begin_object(p->b);
549 json_builder_set_member_name(p->b, "subtitle");
550 json_builder_begin_object(p->b);
552 json_builder_set_member_name(p->b, "language");
553 json_builder_begin_object(p->b);
555 r = _append_lang_properties(l, p);
557 json_builder_end_object(p->b); /* language */
558 json_builder_end_object(p->b); /* subtitle */
560 json_builder_end_object(p->b); /* media */
561 json_builder_end_object(p->b); /* quvi */
562 json_builder_end_object(p->b); /* root */
564 return (r);
567 static gint _foreach_subtitle_lang(const json_t p,
568 const quvi_subtitle_type_t t)
570 quvi_subtitle_lang_t l;
571 gint r;
573 json_builder_set_member_name(p->b, "languages");
574 json_builder_begin_array(p->b);
576 r = EXIT_SUCCESS;
577 while ( (l = quvi_subtitle_lang_next(t)) != NULL && r ==EXIT_SUCCESS)
579 json_builder_begin_object(p->b);
580 r = _append_lang_properties(l, p);
581 json_builder_end_object(p->b);
583 json_builder_end_array(p->b); /* languages */
585 return (r);
588 gint lprint_json_subtitles_available(quvi_t q, quvi_subtitle_t qsub)
590 quvi_subtitle_type_t t;
591 json_t p;
592 gint r;
594 g_assert(qsub != NULL);
595 g_assert(q != NULL);
597 if (_json_handle_new(q, NULL, (gpointer*) &p) != EXIT_SUCCESS)
598 return (EXIT_FAILURE);
600 json_builder_begin_object(p->b); /* root */
602 json_builder_set_member_name(p->b, "quvi");
603 json_builder_begin_object(p->b);
605 json_builder_set_member_name(p->b, "media");
606 json_builder_begin_object(p->b);
608 json_builder_set_member_name(p->b, "subtitle");
609 json_builder_begin_object(p->b);
611 json_builder_set_member_name(p->b, "types");
612 json_builder_begin_array(p->b);
614 r = EXIT_SUCCESS;
615 while ( (t = quvi_subtitle_type_next(qsub)) != NULL && r ==EXIT_SUCCESS)
617 json_builder_begin_object(p->b);
618 _print_stp_d(QUVI_SUBTITLE_TYPE_PROPERTY_FORMAT);
619 _print_stp_d(QUVI_SUBTITLE_TYPE_PROPERTY_TYPE);
620 r = _foreach_subtitle_lang(p, t);
621 json_builder_end_object(p->b);
624 json_builder_end_array(p->b); /* types */
625 json_builder_end_object(p->b); /* subtitle */
627 json_builder_end_object(p->b); /* media */
628 json_builder_end_object(p->b); /* quvi */
629 json_builder_end_object(p->b); /* root */
631 if (r == EXIT_SUCCESS)
632 r = _print_buffer(p);
634 return (_json_handle_free(p, r));
637 #undef _print_slp_s
638 #undef _print_stp_d
640 /* vim: set ts=2 sw=2 tw=72 expandtab: */