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/>.
24 #include <glib/gprintf.h>
25 #include <glib/gi18n.h>
37 static struct linput_s linput
;
38 static struct lopts_s lopts
;
39 extern struct opts_s opts
;
42 static gint
_write_subtitle(quvi_subtitle_lang_t ql
,
43 quvi_subtitle_export_t qse
,
45 lutil_cb_printerr xperr
)
47 gchar
*fname
, *fpath
, *tmp
;
48 const gchar
*data
, *s
;
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
);
69 tmp
= g_path_get_basename(mfpath
);
70 fpath
= lutil_regex_op_apply(rx
, tmp
);
72 lutil_regex_op_free(rx
);
75 fname
= g_path_get_basename(fpath
);
77 data
= quvi_subtitle_export_data(qse
);
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"));
90 if (g_file_set_contents(fpath
, data
, n
, &e
) == FALSE
)
92 xperr(_("while writing: %s: %s"), fpath
, e
->message
);
102 static GSList
*_subtitle_languages(quvi_subtitle_t qsub
)
104 quvi_subtitle_type_t t
;
105 quvi_subtitle_lang_t l
;
109 g_assert(qsub
!= 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
));
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 ");
146 static gchar
*_str_list_to_s(GSList
*l
, const gchar
*f
, const gint n
)
151 memset(&m
, 0, sizeof(struct foreach_s
));
152 m
.s
= g_string_new(NULL
);
156 g_slist_foreach(l
, _foreach_str
, &m
);
159 g_string_free(m
.s
, FALSE
);
163 static void _dump_languages(quvi_subtitle_t qsub
)
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
);
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
;
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
,
198 if (r
== EXIT_SUCCESS
)
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
);
208 xperr(_("libquvi: while exporting subtitle: %s"), quvi_errmsg(q
));
210 quvi_subtitle_export_free(qse
);
213 g_print(_("skip: subtitle extraction\n"));
215 quvi_subtitle_free(qsub
);
220 static void _copy_media_stream(lutil_query_properties_t qps
, quvi_media_t qm
,
223 struct lutil_build_fpath_s b
;
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
;
237 g
.xperr
= qps
->xperr
;
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
);
259 static GSList
*_media_streams(quvi_media_t qm
)
265 while (quvi_media_stream_next(qm
) == QUVI_TRUE
)
267 quvi_media_get(qm
, QUVI_MEDIA_STREAM_PROPERTY_ID
, &s
);
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
)
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
);
292 static void _foreach_media_url(gpointer p
, gpointer userdata
,
295 lutil_query_properties_t qps
;
298 g_assert(userdata
!= NULL
);
301 qps
= (lutil_query_properties_t
) p
;
302 qm
= (quvi_media_t
) userdata
;
304 if (qps
->exit_status
!= EXIT_SUCCESS
)
307 if (opts
.core
.print_streams
== FALSE
)
308 _copy_media_stream(qps
, qm
, url
);
310 _print_streams(qps
, qm
);
313 static void _foreach_playlist_url(gpointer p
, gpointer userdata
,
316 lutil_query_properties_t qps
;
321 g_assert(userdata
!= NULL
);
324 qps
= (lutil_query_properties_t
) p
;
325 qp
= (quvi_playlist_t
) userdata
;
327 if (qps
->exit_status
!= EXIT_SUCCESS
)
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
);
338 if (qps
->exit_status
!= EXIT_SUCCESS
)
343 static void _foreach_subtitle_url(gpointer p
, gpointer userdata
,
346 lutil_query_properties_t qps
;
347 quvi_subtitle_t qsub
;
349 g_assert(userdata
!= NULL
);
352 qps
= (lutil_query_properties_t
) p
;
353 qsub
= (quvi_subtitle_t
) userdata
;
355 if (qps
->exit_status
!= EXIT_SUCCESS
)
358 _dump_languages(qsub
);
361 static gint
_cleanup(const gint r
)
363 linput_free(&linput
);
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
;
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: */