FIX: quvi-get: Use "default" with --print-streams
[quvi-tool.git] / src / builtin / get.c
blob1c908114796a18ad7df0dda2051d6ab0c03ff4c4
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 #include "config.h"
23 #include <stdlib.h>
24 #include <glib/gprintf.h>
25 #include <glib/gi18n.h>
26 #include <quvi.h>
28 #include "lprint.h"
29 #include "linput.h"
30 #include "lopts.h"
31 #include "lutil.h"
32 #include "lget.h"
33 #include "setup.h"
34 #include "opts.h"
35 #include "cmd.h"
37 static struct linput_s linput;
38 static struct lopts_s lopts;
39 extern struct opts_s opts;
40 static quvi_t q;
42 static gint _write_subtitle(quvi_subtitle_lang_t ql,
43 quvi_subtitle_export_t qse,
44 const gchar *mfpath,
45 lutil_cb_printerr xperr)
47 gchar *fname, *fpath, *tmp;
48 const gchar *data, *s;
49 lutil_regex_op_t rx;
50 GError *e;
51 gsize n;
52 gint r;
55 * Produce the output fpath for the subtitle file by using the media
56 * fpath as a template: replace the media file extension with the
57 * subtitle file extension.
59 * The '%x' is being used only to pass the lutil_regex_op_new regular
60 * expression validation step. This could be anything matching '%\w'.
63 tmp = g_strdup_printf("%%x:s/\\.\\w+$/.%s/",
64 opts.core.subtitle_export_format);
66 rx = lutil_regex_op_new(tmp, NULL);
67 g_free(tmp);
69 tmp = g_path_get_basename(mfpath);
70 fpath = lutil_regex_op_apply(rx, tmp);
72 lutil_regex_op_free(rx);
73 g_free(tmp);
75 fname = g_path_get_basename(fpath);
77 data = quvi_subtitle_export_data(qse);
78 n = strlen(data);
80 quvi_subtitle_lang_get(ql, QUVI_SUBTITLE_LANG_PROPERTY_ID, &s);
82 g_print(_("file: %s [subtitle]\n"), fname);
83 g_print(_(" content length: %"G_GSIZE_FORMAT" bytes"), n);
84 g_print(_(" type/language: %s"), s);
85 g_print(_(" mode: write\n"));
87 r = EXIT_SUCCESS;
88 e = NULL;
90 if (g_file_set_contents(fpath, data, n, &e) == FALSE)
92 xperr(_("while writing: %s: %s"), fpath, e->message);
93 g_error_free(e);
94 r = EXIT_FAILURE;
96 g_free(fname);
97 g_free(fpath);
99 return (r);
102 static GSList *_subtitle_languages(quvi_subtitle_t qsub)
104 quvi_subtitle_type_t t;
105 quvi_subtitle_lang_t l;
106 const gchar *s;
107 GSList *r;
109 g_assert(qsub != NULL);
111 r = NULL;
112 while ( (t = quvi_subtitle_type_next(qsub)) != NULL)
114 while ( (l = quvi_subtitle_lang_next(t)) != NULL)
116 quvi_subtitle_lang_get(l, QUVI_SUBTITLE_LANG_PROPERTY_ID, &s);
117 r = g_slist_prepend(r, g_strdup(s));
120 return (g_slist_reverse(r));
123 struct foreach_s
125 const gchar *f;
126 GString *s;
127 gint i;
128 gint n;
131 typedef struct foreach_s *foreach_t;
133 static void _foreach_str(gpointer p, gpointer userdata)
135 foreach_t m = (foreach_t) userdata;
137 g_string_append_printf(m->s, m->f, (gchar*) p);
139 if (++(m->i) == m->n)
141 g_string_append(m->s, "\n ");
142 m->i = 0;
146 static gchar *_str_list_to_s(GSList *l, const gchar *f, const gint n)
148 struct foreach_s m;
149 gchar *r;
151 memset(&m, 0, sizeof(struct foreach_s));
152 m.s = g_string_new(NULL);
153 m.f = f;
154 m.n = n;
156 g_slist_foreach(l, _foreach_str, &m);
157 r = m.s->str;
159 g_string_free(m.s, FALSE);
160 return (r);
163 static void _dump_languages(quvi_subtitle_t qsub)
165 GSList *l;
166 gchar *s;
168 l = _subtitle_languages(qsub);
169 s = _str_list_to_s(l, "%10s ", 6);
171 g_print(_("subtitles (found):\n %s\n"), (strlen(s) ==0) ? _("none"):s);
173 lutil_slist_free_full(l, (GFunc) g_free);
174 g_free(s);
177 static gint _copy_subtitle(const gchar *mfpath, const gchar *url,
178 lutil_cb_printerr xperr)
180 quvi_subtitle_lang_t ql;
181 quvi_subtitle_t qsub;
182 gint r;
184 if (opts.core.subtitle_language == NULL)
185 return (EXIT_SUCCESS);
187 qsub = quvi_subtitle_new(q, url);
188 if (quvi_ok(q) == FALSE)
190 xperr(_("libquvi: while querying subtitles: %s"), quvi_errmsg(q));
191 return (EXIT_FAILURE);
194 _dump_languages(qsub);
196 r = lutil_choose_subtitle(q, qsub, opts.core.subtitle_language,
197 xperr, &ql, FALSE);
198 if (r == EXIT_SUCCESS)
200 if (ql != NULL)
202 quvi_subtitle_export_t qse;
204 qse = quvi_subtitle_export_new(ql, opts.core.subtitle_export_format);
205 if (quvi_ok(q) == TRUE)
206 r = _write_subtitle(ql, qse, mfpath, xperr);
207 else
208 xperr(_("libquvi: while exporting subtitle: %s"), quvi_errmsg(q));
210 quvi_subtitle_export_free(qse);
212 else
213 g_print(_("skip: subtitle extraction\n"));
215 quvi_subtitle_free(qsub);
217 return (r);
220 static void _copy_media_stream(lutil_query_properties_t qps, quvi_media_t qm,
221 const gchar *url)
223 struct lutil_build_fpath_s b;
224 struct lget_s g;
226 memset(&b, 0, sizeof(struct lutil_build_fpath_s));
227 memset(&g, 0, sizeof(struct lget_s));
229 b.output_regex = opts.get.output_regex;
230 b.output_file = opts.get.output_file;
231 b.output_name = opts.get.output_name;
232 b.output_dir = opts.get.output_dir;
233 b.xperr = qps->xperr;
234 b.qm = qm;
236 g.build_fpath = &b;
237 g.xperr = qps->xperr;
238 g.qm = qm;
239 g.q = q;
241 g.opts.overwrite_if_exists = opts.get.overwrite;
242 g.opts.skip_transfer = opts.get.skip_transfer;
243 g.opts.resume_from = opts.get.resume_from;
244 g.opts.stream = opts.core.stream;
246 g.opts.exec.external = (const gchar**) opts.exec.external;
247 g.opts.exec.enable_stderr = opts.exec.enable_stderr;
248 g.opts.exec.enable_stdout = opts.exec.enable_stdout;
249 g.opts.exec.dump_argv = opts.exec.dump_argv;
251 qps->exit_status = lget_new(&g);
253 if (qps->exit_status == EXIT_SUCCESS)
254 qps->exit_status = _copy_subtitle(g.result.fpath, url, qps->xperr);
256 lget_free(&g);
259 static GSList *_media_streams(quvi_media_t qm)
261 const gchar *s;
262 GSList *r;
264 r = NULL;
265 while (quvi_media_stream_next(qm) == QUVI_TRUE)
267 quvi_media_get(qm, QUVI_MEDIA_STREAM_PROPERTY_ID, &s);
268 if (strlen(s) >0)
269 r = g_slist_prepend(r, g_strdup(s));
272 if (g_slist_length(r) ==0)
273 r = g_slist_prepend(r, g_strdup(_("default")));
275 return (g_slist_reverse(r));
278 static void _print_streams(lutil_query_properties_t qps, quvi_media_t qm)
280 GSList *l;
281 gchar *s;
283 l = _media_streams(qm);
284 s = _str_list_to_s(l, "%22s ", 3);
286 g_print(_("streams (found):\n %s\n"), s);
288 lutil_slist_free_full(l, (GFunc) g_free);
289 g_free(s);
292 static void _foreach_media_url(gpointer p, gpointer userdata,
293 const gchar *url)
295 lutil_query_properties_t qps;
296 quvi_media_t qm;
298 g_assert(userdata != NULL);
299 g_assert(p != NULL);
301 qps = (lutil_query_properties_t) p;
302 qm = (quvi_media_t) userdata;
304 if (qps->exit_status != EXIT_SUCCESS)
305 return;
307 if (opts.core.print_streams == FALSE)
308 _copy_media_stream(qps, qm, url);
309 else
310 _print_streams(qps, qm);
313 static void _foreach_playlist_url(gpointer p, gpointer userdata,
314 const gchar *url)
316 lutil_query_properties_t qps;
317 quvi_playlist_t qp;
318 quvi_media_t qm;
319 gchar *m_url;
321 g_assert(userdata != NULL);
322 g_assert(p != NULL);
324 qps = (lutil_query_properties_t) p;
325 qp = (quvi_playlist_t) userdata;
327 if (qps->exit_status != EXIT_SUCCESS)
328 return;
330 while (quvi_playlist_media_next(qp) == QUVI_TRUE)
332 quvi_playlist_get(qp, QUVI_PLAYLIST_MEDIA_PROPERTY_URL, &m_url);
333 qm = quvi_media_new(qps->q, m_url);
335 _foreach_media_url(qps, qm, m_url);
336 quvi_media_free(qm);
338 if (qps->exit_status != EXIT_SUCCESS)
339 return;
343 static void _foreach_subtitle_url(gpointer p, gpointer userdata,
344 const gchar *url)
346 lutil_query_properties_t qps;
347 quvi_subtitle_t qsub;
349 g_assert(userdata != NULL);
350 g_assert(p != NULL);
352 qps = (lutil_query_properties_t) p;
353 qsub = (quvi_subtitle_t) userdata;
355 if (qps->exit_status != EXIT_SUCCESS)
356 return;
358 _dump_languages(qsub);
361 static gint _cleanup(const gint r)
363 linput_free(&linput);
364 quvi_free(q);
365 return (r);
368 gint cmd_get(gint argc, gchar **argv)
370 struct setup_query_s sq;
372 if (setup_opts(argc, argv, &lopts) != EXIT_SUCCESS)
373 return (EXIT_FAILURE);
375 if (lutil_parse_input(&linput, (const gchar**) opts.rargs) != EXIT_SUCCESS)
376 return (EXIT_FAILURE);
378 if (setup_quvi(&q) != EXIT_SUCCESS)
380 linput_free(&linput);
381 return (EXIT_FAILURE);
384 memset(&sq, 0, sizeof(struct setup_query_s));
386 sq.force_subtitle_mode = opts.core.print_subtitles;
388 sq.activity.playlist = _foreach_playlist_url;
389 sq.activity.subtitle = _foreach_subtitle_url;
390 sq.activity.media = _foreach_media_url;
392 sq.perr = lutil_print_stderr_unless_quiet;
393 sq.xperr = lprint_enum_errmsg;
395 sq.linput = &linput;
396 sq.q = q;
398 if (setup_query(&sq) != EXIT_SUCCESS)
399 return (_cleanup(EXIT_FAILURE));
401 return (_cleanup(EXIT_SUCCESS));
404 /* vim: set ts=2 sw=2 tw=72 expandtab: */