2 * Copyright (C) 2013 Toni Gundogdu <legatvs@gmail.com>
4 * This file is part of libquvi <http://quvi.sourceforge.net/>.
6 * This library 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 library 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 library. If not, see
18 * <http://www.gnu.org/licenses/>.
22 * NOTE: The error messages produced in these functions are intended for
23 * developers. They would typically be seen when a new script is
24 * being developed or an old one is being maintained.
26 * These messages should be clear, indicating the actual error,
27 * minimizing the time spent on locating the problem in the script.
38 #include "_quvi_subtitle_s.h"
39 #include "_quvi_script_s.h"
41 #include "misc/subtitle.h"
42 #include "lua/setfield.h"
46 static const gchar script_func
[] = "parse";
48 /* Verify that the language has an ID (if there are >1 languages). */
49 static void _chk_lang_id(lua_State
*l
, _quvi_subtitle_type_t qst
,
50 _quvi_subtitle_lang_t qsl
, const gchar
*script_path
,
53 if (g_slist_length(qst
->languages
) <2)
58 g_warning("%s: %s: `qargs.%s[%d].%s' should not be empty; "
59 "each language should have an ID when there are >1 languages",
60 script_path
, script_func
, SUS_SUBTITLES
, i
, SUSSL_ID
);
64 typedef void (*foreach_cb
)(lua_State
*, _quvi_subtitle_type_t
,
65 const gchar
*, const gint
);
67 /* Process a "sublevel" of a dictionary, e.g. qargs.subtitles.lang */
68 static void _chk_subtitle_sublevel(lua_State
*l
, const gchar
*level
,
69 _quvi_subtitle_type_t qst
,
70 const gchar
*script_path
,
71 const foreach_cb cb
, const gint i
)
73 if (lua_isstring(l
, LI_KEY
) && lua_istable(l
, LI_VALUE
))
75 if (g_strcmp0(lua_tostring(l
, LI_KEY
), level
) ==0)
76 cb(l
, qst
, script_path
, i
);
80 /* Return a new language handle. */
81 static gpointer
_subtitle_lang_new(_quvi_subtitle_type_t qst
)
83 _quvi_subtitle_lang_t qsl
= g_new0(struct _quvi_subtitle_lang_s
, 1);
85 qsl
->handle
.quvi
= qst
->handle
.quvi
;
87 qsl
->translated
= g_string_new(NULL
);
88 qsl
->original
= g_string_new(NULL
);
89 qsl
->code
= g_string_new(NULL
);
90 qsl
->url
= g_string_new(NULL
);
91 qsl
->id
= g_string_new(NULL
);
93 qsl
->format
= qst
->format
;
97 /* Return a new data handle. */
98 static gpointer
_subtitle_type_new(const _quvi_subtitle_t qsub
)
100 _quvi_subtitle_type_t qst
= g_new0(struct _quvi_subtitle_type_s
, 1);
102 qst
->handle
.quvi
= qsub
->handle
.quvi
;
109 /* Must have at least one language URL. */
110 static _quvi_subtitle_lang_t
_chk_url(lua_State
*l
, const gchar
*script_path
,
111 _quvi_subtitle_lang_t qsl
, gint i
)
113 if (qsl
->url
->len
==0)
115 m_subtitle_lang_free(qsl
);
117 luaL_error(l
, "%s: %s: must return `qargs.%s[%d].%s[1].%s'",
118 script_path
, script_func
, SUS_SUBTITLES
, i
,
119 SUSS_LANG
, SUSSL_URL
);
124 /* Return a new lang handle. */
125 static _quvi_subtitle_lang_t
_new_lang(lua_State
*l
, const gchar
*script_path
,
126 const _quvi_subtitle_type_t qst
,
129 _quvi_subtitle_lang_t qsl
= _subtitle_lang_new(qst
);
131 while (lua_next(l
, LI_KEY
))
133 l_chk_assign_s(l
, SUSSL_TRANSLATED
, qsl
->translated
, TRUE
, FALSE
);
134 l_chk_assign_s(l
, SUSSL_ORIGINAL
, qsl
->original
, TRUE
, FALSE
);
135 l_chk_assign_s(l
, SUSSL_CODE
, qsl
->code
, TRUE
, FALSE
);
136 l_chk_assign_s(l
, SUSSL_URL
, qsl
->url
, TRUE
, TRUE
);
137 l_chk_assign_s(l
, SUSSL_ID
, qsl
->id
, TRUE
, FALSE
);
140 return (_chk_url(l
, script_path
, qsl
, i
));
143 /* For each qargs.subtitles.lang property. */
144 static void _foreach_lang_property(lua_State
*l
, _quvi_subtitle_type_t qst
,
145 const gchar
*script_path
, const gint i
)
147 _quvi_subtitle_lang_t qsl
;
153 while (lua_next(l
, LI_KEY
))
155 if (lua_istable(l
, LI_VALUE
))
157 qsl
= _new_lang(l
, script_path
, qst
, ++j
);
158 _chk_lang_id(l
, qst
, qsl
, script_path
, j
);
159 qst
->languages
= g_slist_prepend(qst
->languages
, qsl
);
165 /* Verify required subtitle data properties. */
166 static gpointer
_chk_req_type(lua_State
*l
, _quvi_subtitle_type_t qst
,
167 const gint i
, const gchar
*script_path
)
169 static const gchar
*_E
= "%s: %s: must return `qargs.%s[%d].%s'";
173 luaL_error(l
, _E
, script_path
, script_func
,
174 SUS_SUBTITLES
, i
, SUSS_FORMAT
);
179 luaL_error(l
, _E
, script_path
, script_func
,
180 SUS_SUBTITLES
, i
, SUSS_TYPE
);
183 /* Not all videos have subtitles of any kind. */
184 if (g_slist_length(qst
->languages
) ==0)
186 m_subtitle_type_free(qst
);
191 if (g_slist_length(qst
->languages
) ==0)
193 luaL_error(l
, "%s: %s: qargs.%s[%d].%s must not be empty",
194 script_path
, script_func
, SUS_SUBTITLES
, i
, SUSS_LANG
);
198 qst
->languages
= g_slist_reverse(qst
->languages
);
202 /* Return a new data handle. */
203 static _quvi_subtitle_type_t
_new_type(lua_State
*l
, _quvi_subtitle_t qsub
,
204 const gchar
*script_path
, const gint i
)
206 _quvi_subtitle_type_t qst
= _subtitle_type_new(qsub
);
208 while (lua_next(l
, LI_KEY
))
210 _chk_subtitle_sublevel(l
, SUSS_LANG
, qst
, script_path
,
211 _foreach_lang_property
, i
);
212 l_chk_assign_n(l
, SUSS_FORMAT
, &qst
->format
);
213 l_chk_assign_n(l
, SUSS_TYPE
, &qst
->type
);
216 return (_chk_req_type(l
, qst
, i
, script_path
));
219 /* For each qargs.subtitle */
220 static void _foreach_subtitle(lua_State
*l
, _quvi_subtitle_t qsub
,
221 const gchar
*script_path
)
223 _quvi_subtitle_type_t qst
;
229 while (lua_next(l
, LI_KEY
))
231 if (lua_istable(l
, LI_VALUE
))
233 qst
= _new_type(l
, qsub
, script_path
, ++i
);
235 qsub
->types
= g_slist_prepend(qsub
->types
, qst
);
239 qsub
->types
= g_slist_reverse(qsub
->types
);
242 static void _chk_subtitles(lua_State
*l
, _quvi_subtitle_t qsub
,
243 const gchar
*script_path
)
245 lua_pushstring(l
, SUS_SUBTITLES
);
246 lua_gettable(l
, LI_KEY
);
248 if (lua_istable(l
, LI_VALUE
))
249 _foreach_subtitle(l
, qsub
, script_path
);
252 static const gchar
*_E
=
253 "%s: %s: must return a dictionary containing the `qargs.%s'";
255 luaL_error(l
, _E
, script_path
, script_func
, SUS_SUBTITLES
);
260 extern gint
c_reset(_quvi_t
);
262 QuviError
l_exec_subtitle_script_parse(gpointer p
, GSList
*sl
)
264 _quvi_subtitle_t qsub
;
268 qsub
= (_quvi_subtitle_t
) p
;
269 l
= qsub
->handle
.quvi
->handle
.lua
;
271 c_reset(qsub
->handle
.quvi
);
273 qs
= (_quvi_script_t
) sl
->data
;
274 lua_getglobal(l
, script_func
);
276 if (!lua_isfunction(l
, -1))
278 luaL_error(l
, "%s: the function `%s' was not found",
279 qs
->fpath
->str
, script_func
);
283 l_set_reg_userdata(l
, USERDATA_QUVI_T
, (gpointer
) qsub
->handle
.quvi
);
284 l_setfield_s(l
, SUS_INPUT_URL
, qsub
->url
.input
->str
, -1);
286 if (lua_pcall(l
, 1, 1, 0))
288 g_string_assign(qsub
->handle
.quvi
->status
.errmsg
, lua_tostring(l
, -1));
289 return (QUVI_ERROR_SCRIPT
);
292 if (!lua_istable(l
, -1))
294 static const gchar
*_E
=
295 "%s: %s: must return a dictionary, this is typically the `qargs'";
297 luaL_error(l
, _E
, qs
->fpath
->str
, script_func
);
300 _chk_subtitles(l
, qsub
, qs
->fpath
->str
);
306 /* vim: set ts=2 sw=2 tw=72 expandtab: */