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. */
26 #include <json-glib/json-glib.h>
27 #include <glib/gprintf.h>
30 #if JSON_MAJOR_VERSION >=0 && JSON_MINOR_VERSION >=14
45 typedef struct json_s
*json_t
;
47 static gint
_json_handle_new(quvi_t q
, quvi_media_t qm
, gpointer
*dst
)
51 g_assert(dst
!= NULL
);
53 p
= g_new0(struct json_s
, 1);
54 p
->b
= json_builder_new();
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
;
80 static gint
_print_buffer(const json_t p
)
88 g
= json_generator_new();
89 r
= json_builder_get_root(p
->b
);
91 json_generator_set_root(g
, r
);
93 json_generator_set_pretty(g
, 1);
95 s
= json_generator_to_data(g
, NULL
);
103 return (EXIT_SUCCESS
);
106 extern const gchar
*reserved_chars
;
108 void lprint_json_errmsg(const gchar
*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
);
124 typedef lprint_cb_errmsg cem
;
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
);
163 gchar
*e
= g_uri_escape_string(s
, reserved_chars
, FALSE
);
164 json_builder_add_string_value(p
->b
, e
);
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
)
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)\
182 if (_mp_s(p, n, #n) != EXIT_SUCCESS)\
183 return (EXIT_FAILURE);\
186 static gint
_mp_d(const json_t p
, const QuviMediaProperty qmp
, const gchar
*n
)
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)\
195 if (_mp_d(p, n, #n) != EXIT_SUCCESS)\
196 return (EXIT_FAILURE);\
199 static gint
_mi_s(const json_t p
, const quvi_http_metainfo_t qmi
,
200 const QuviHTTPMetaInfoProperty qmip
, const gchar
*n
)
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)\
209 if (_mi_s(p, qmi, n, #n) != EXIT_SUCCESS)\
210 return (EXIT_FAILURE);\
213 static gint
_mi_d(const json_t p
, const quvi_http_metainfo_t qmi
,
214 const QuviHTTPMetaInfoProperty qmip
, const gchar
*n
)
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)\
223 if (_mi_d(p, qmi, n, #n) != EXIT_SUCCESS)\
224 return (EXIT_FAILURE);\
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
);
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
);
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
)
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
);
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
));
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
);
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
)
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)\
356 if (_pp_s(p, qp, n, #n) != EXIT_SUCCESS)\
357 return (EXIT_FAILURE);\
360 static gint
_pp_d(const json_t p
, const quvi_playlist_t qp
,
361 const QuviPlaylistProperty qpp
, const gchar
*n
)
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)\
370 if (_pp_d(p, qp, n, #n) != EXIT_SUCCESS)\
371 return (EXIT_FAILURE);\
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
);
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
)
440 g_assert(data
!= NULL
);
441 g_assert(qs
!= NULL
);
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
);
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
);
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
)
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)\
503 if (_stp_d(p, t, n, #n) != EXIT_SUCCESS)\
504 return (EXIT_FAILURE);\
507 static gint
_slp_s(const json_t p
, const quvi_subtitle_lang_t qsl
,
508 const QuviSubtitleLangProperty qslp
, const gchar
*n
)
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)\
517 if (_slp_s(p, l, n, #n) != EXIT_SUCCESS)\
518 return (EXIT_FAILURE);\
521 static gint
_append_lang_properties(const quvi_subtitle_lang_t l
,
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
);
533 lprint_json_subtitle_lang_properties(quvi_subtitle_lang_t l
, gpointer data
)
538 g_assert(data
!= NULL
);
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 */
567 static gint
_foreach_subtitle_lang(const json_t p
,
568 const quvi_subtitle_type_t t
)
570 quvi_subtitle_lang_t l
;
573 json_builder_set_member_name(p
->b
, "languages");
574 json_builder_begin_array(p
->b
);
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 */
588 gint
lprint_json_subtitles_available(quvi_t q
, quvi_subtitle_t qsub
)
590 quvi_subtitle_type_t t
;
594 g_assert(qsub
!= 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
);
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
));
640 /* vim: set ts=2 sw=2 tw=72 expandtab: */