370bc561b9a8fba76890c17bc64a0c626f5e64ff
2 * Copyright (C) 2012,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_media_s.h"
39 #include "_quvi_script_s.h"
41 #include "lua/setfield.h"
46 static const gchar script_func
[] = "parse";
48 static void _foreach_video_property(lua_State
*l
, _quvi_media_t qm
,
49 _quvi_media_stream_t qms
)
52 while (lua_next(l
, LI_KEY
))
54 l_chk_assign_n(l
, MSS_VIDEO_BITRATE_KBIT_S
, &qms
->video
.bitrate_kbit_s
);
55 l_chk_assign_s(l
, MSS_VIDEO_ENCODING
, qms
->video
.encoding
, TRUE
);
56 l_chk_assign_n(l
, MSS_VIDEO_HEIGHT
, &qms
->video
.height
);
57 l_chk_assign_n(l
, MSS_VIDEO_WIDTH
, &qms
->video
.width
);
62 static void _foreach_audio_property(lua_State
*l
, _quvi_media_t qm
,
63 _quvi_media_stream_t qms
)
66 while (lua_next(l
, LI_KEY
))
68 l_chk_assign_n(l
, MSS_AUDIO_BITRATE_KBIT_S
, &qms
->audio
.bitrate_kbit_s
);
69 l_chk_assign_s(l
, MSS_AUDIO_ENCODING
, qms
->audio
.encoding
, TRUE
);
74 static void _foreach_flag_property(lua_State
*l
, _quvi_media_t qm
,
75 _quvi_media_stream_t qms
)
78 while (lua_next(l
, LI_KEY
))
80 l_chk_assign_b(l
, MSS_FLAGS_BEST
, &qms
->flags
.best
);
85 typedef void (*foreach_cb
)(lua_State
*, _quvi_media_t
, _quvi_media_stream_t
);
87 static void _chk_stream_sublevel(const gchar
*level
, lua_State
*l
,
88 _quvi_media_t qm
, _quvi_media_stream_t qms
,
91 if (lua_isstring(l
, LI_KEY
) && lua_istable(l
, LI_VALUE
))
93 if (g_strcmp0(lua_tostring(l
, LI_KEY
), level
) == 0)
98 static gpointer
_media_stream_new()
100 _quvi_media_stream_t qms
= g_new0(struct _quvi_media_stream_s
, 1);
101 qms
->video
.encoding
= g_string_new(NULL
);
102 qms
->audio
.encoding
= g_string_new(NULL
);
103 qms
->container
= g_string_new(NULL
);
104 qms
->url
= g_string_new(NULL
);
105 qms
->id
= g_string_new(NULL
);
109 static void _has_stream_url(lua_State
*l
, _quvi_media_stream_t qms
,
110 const gchar
*script_path
, const gint i
)
112 if (qms
->url
->len
==0)
114 static const gchar
*_E
=
115 "%s: %s: must return a media stream URL in `qargs.%s[%d].%s'";
117 luaL_error(l
, _E
, script_path
, script_func
, MS_STREAMS
, i
, MSS_URL
);
121 static _quvi_media_stream_t
_new_stream(lua_State
*l
, _quvi_media_t qm
,
122 const gchar
*script_path
,
125 _quvi_media_stream_t qms
= _media_stream_new();
128 while (lua_next(l
, LI_KEY
))
130 _chk_stream_sublevel(MSS_VIDEO
, l
, qm
, qms
, _foreach_video_property
);
131 _chk_stream_sublevel(MSS_AUDIO
, l
, qm
, qms
, _foreach_audio_property
);
132 _chk_stream_sublevel(MSS_FLAGS
, l
, qm
, qms
, _foreach_flag_property
);
133 l_chk_assign_s(l
, MSS_CONTAINER
, qms
->container
, TRUE
);
134 l_chk_assign_s(l
, MSS_URL
, qms
->url
, TRUE
);
135 l_chk_assign_s(l
, MSS_ID
, qms
->id
, TRUE
);
138 _has_stream_url(l
, qms
, script_path
, i
);
142 static void _chk_stream_ids(lua_State
*l
, _quvi_media_t qm
,
143 const gchar
*script_path
)
145 _quvi_media_stream_t qms
;
149 if (g_slist_length(qm
->streams
) < 2)
157 qms
= (_quvi_media_stream_t
) curr
->data
;
158 if (qms
->id
->len
==0)
160 g_warning("%s: %s: `qargs.%s[%d].%s' should not be empty; "
161 "each stream should have an ID when there are >1 "
163 script_path
, script_func
, MS_STREAMS
, i
, MSS_ID
);
165 curr
= g_slist_next(curr
);
170 static void _foreach_stream(lua_State
*l
, _quvi_media_t qm
,
171 const gchar
*script_path
)
176 while (lua_next(l
, LI_KEY
))
178 if (lua_istable(l
, LI_VALUE
))
180 _quvi_media_stream_t qms
= _new_stream(l
, qm
, script_path
, ++i
);
181 qm
->streams
= g_slist_prepend(qm
->streams
, qms
);
185 qm
->streams
= g_slist_reverse(qm
->streams
);
186 _chk_stream_ids(l
, qm
, script_path
);
189 /* Check for 'qargs.streams'. This is the only mandatory data. */
190 static void _chk_streams(lua_State
*l
, _quvi_media_t qm
,
191 const gchar
*script_path
)
193 lua_pushstring(l
, MS_STREAMS
);
194 lua_gettable(l
, LI_KEY
);
196 if (lua_istable(l
, LI_VALUE
))
197 _foreach_stream(l
, qm
, script_path
);
200 static const gchar
*_E
=
201 "%s: %s: must return a dictionary containing the `qargs.%s'";
203 luaL_error(l
, _E
, script_path
, script_func
, MS_STREAMS
);
207 if (g_slist_length(qm
->streams
) ==0)
209 luaL_error(l
, "%s: %s: must return at least one media stream",
210 script_path
, script_func
);
214 /* Check for optional media properties, e.g. title. */
215 static void _chk_optional(lua_State
*l
, _quvi_media_t qm
)
218 while (lua_next(l
, LI_KEY
))
220 l_chk_assign_n(l
, MS_START_TIME_MS
, &qm
->start_time_ms
);
221 l_chk_assign_n(l
, MS_DURATION_MS
, &qm
->duration_ms
);
222 l_chk_assign_s(l
, MS_THUMB_URL
, qm
->url
.thumbnail
, TRUE
);
223 l_chk_assign_s(l
, MS_TITLE
, qm
->title
, TRUE
);
224 l_chk_assign_s(l
, MS_ID
, qm
->id
, TRUE
);
229 /* Check for the goto URL instruction. */
230 static gboolean
_chk_goto_instr(lua_State
*l
, _quvi_media_t qm
)
233 while (lua_next(l
, LI_KEY
))
235 l_chk_assign_s(l
, MS_GOTO_URL
, qm
->url
.redirect_to
, TRUE
);
238 return ((qm
->url
.redirect_to
->len
>0) ? TRUE
:FALSE
);
241 extern QuviError
l_exec_util_convert_entities(_quvi_media_t
);
242 extern gint
c_reset(_quvi_t
);
244 QuviError
l_exec_media_script_parse(gpointer p
, GSList
*sl
)
251 qm
= (_quvi_media_t
) p
;
254 l
= qm
->handle
.quvi
->handle
.lua
;
255 c_reset(qm
->handle
.quvi
);
257 qs
= (_quvi_script_t
) sl
->data
;
258 lua_getglobal(l
, script_func
);
260 if (!lua_isfunction(l
, -1))
262 luaL_error(l
, "%s: the function `%s' was not found",
263 qs
->fpath
->str
, script_func
);
267 l_set_reg_userdata(l
, USERDATA_QUVI_T
, (gpointer
) qm
->handle
.quvi
);
268 l_setfield_s(l
, MS_INPUT_URL
, qm
->url
.input
->str
, -1);
270 if (lua_pcall(l
, 1, 1, 0))
272 g_string_assign(qm
->handle
.quvi
->status
.errmsg
, lua_tostring(l
, -1));
273 return (QUVI_ERROR_SCRIPT
);
276 if (!lua_istable(l
, -1))
278 static const gchar
*_E
=
279 "%s: %s: must return a dictionary, this is typically the `qargs'";
281 luaL_error(l
, _E
, qs
->fpath
->str
, script_func
);
284 if (_chk_goto_instr(l
, qm
) == FALSE
)
285 _chk_streams(l
, qm
, qs
->fpath
->str
);
287 _chk_optional(l
, qm
);
289 if (qm
->title
->len
>0)
290 rc
= l_exec_util_convert_entities(qm
);
296 /* vim: set ts=2 sw=2 tw=72 expandtab: */