quvi 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/quvi_ext/quvi_ext.c +235 -21
- data/lib/quvi.rb +58 -0
- data/lib/quvi/handle.rb +12 -2
- data/lib/quvi/version.rb +2 -2
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df4e609a0c156ac9c3078066ad4085bda633d045
|
4
|
+
data.tar.gz: 19b0599fbe1c32905cfa0037a55ba2c709785615
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1f209a0b4fe186e218a788bb9552cdc037bbebb0f04d13d3cda2f424af0284c35dd0bc2e65f295c3c416ba3cffc80fda27bdd8d72f677e99ca7445307007880
|
7
|
+
data.tar.gz: c76c59aa666494cee48d5e3522df85dbfe280835d48c1721be25add4483f3cd23f851caa03c589af688d651ccc8ef57e1cb0354d9d2101ddb73d676d7ba3aa62
|
data/ext/quvi_ext/quvi_ext.c
CHANGED
@@ -14,14 +14,33 @@ VALUE qv_eError;
|
|
14
14
|
|
15
15
|
VALUE qv_DEFAULT_USER_AGENT;
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
VALUE qv_sym_any;
|
18
|
+
VALUE qv_sym_autoproxy;
|
19
|
+
VALUE qv_sym_media;
|
20
|
+
VALUE qv_sym_online;
|
21
|
+
VALUE qv_sym_playlist;
|
22
|
+
VALUE qv_sym_subtitle;
|
23
|
+
VALUE qv_sym_type;
|
24
|
+
VALUE qv_sym_user_agent;
|
25
|
+
VALUE qv_sym_export_format;
|
26
|
+
VALUE qv_sym_filepath;
|
27
|
+
VALUE qv_sym_domains;
|
28
|
+
VALUE qv_sym_sha1;
|
29
|
+
VALUE qv_sym_title;
|
30
|
+
VALUE qv_sym_id;
|
31
|
+
VALUE qv_sym_thumbnail_url;
|
32
|
+
VALUE qv_sym_start_time_ms;
|
33
|
+
VALUE qv_sym_duration_ms;
|
34
|
+
VALUE qv_sym_video_height;
|
35
|
+
VALUE qv_sym_video_width;
|
36
|
+
VALUE qv_sym_video_encoding;
|
37
|
+
VALUE qv_sym_video_bitrate_kbit_s;
|
38
|
+
VALUE qv_sym_audio_encoding;
|
39
|
+
VALUE qv_sym_audio_bitrate_kbit_s;
|
40
|
+
VALUE qv_sym_container;
|
41
|
+
VALUE qv_sym_url;
|
42
|
+
VALUE qv_sym_streams;
|
43
|
+
VALUE qv_sym_best;
|
25
44
|
|
26
45
|
typedef struct qv_handle_st
|
27
46
|
{
|
@@ -45,21 +64,21 @@ static void qv_handle_free(void *ptr)
|
|
45
64
|
}
|
46
65
|
|
47
66
|
#define qv_raise(handle, message) qv_raise_at(handle, message, __FILE__, __LINE__)
|
48
|
-
static void qv_raise_at(qv_handle_t *handle,
|
67
|
+
static void qv_raise_at(qv_handle_t *handle, VALUE message, const char *file, int line)
|
49
68
|
{
|
50
69
|
VALUE exc, str;
|
51
70
|
const char *qv_msg;
|
52
71
|
char buf[10];
|
53
72
|
int qv_code;
|
54
73
|
|
55
|
-
str =
|
74
|
+
str = rb_str_new_shared(message);
|
56
75
|
qv_msg = quvi_errmsg(handle->q);
|
57
76
|
qv_code = quvi_errcode(handle->q);
|
58
77
|
if (qv_msg) {
|
59
|
-
|
78
|
+
snprintf(buf, 10, ": (0x%02x) \"", qv_code);
|
79
|
+
rb_str_buf_cat_ascii(str, buf);
|
60
80
|
rb_str_buf_cat_ascii(str, qv_msg);
|
61
81
|
rb_str_buf_cat_ascii(str, "\" ");
|
62
|
-
snprintf(buf, 10, "\" (%d)", qv_code);
|
63
82
|
}
|
64
83
|
rb_str_buf_cat_ascii(str, " at ");
|
65
84
|
rb_str_buf_cat_ascii(str, file);
|
@@ -101,7 +120,7 @@ VALUE qv_handle_init(int argc, VALUE *argv, VALUE self)
|
|
101
120
|
}
|
102
121
|
handle->q = quvi_new();
|
103
122
|
if (quvi_ok(handle->q) == QUVI_FALSE) {
|
104
|
-
qv_raise(handle, "unable create quvi_t handle");
|
123
|
+
qv_raise(handle, rb_str_new_cstr("unable create quvi_t handle"));
|
105
124
|
}
|
106
125
|
rb_funcall2(self, rb_intern("autoproxy="), 1, &autoproxy);
|
107
126
|
rb_funcall2(self, rb_intern("user_agent="), 1, &user_agent);
|
@@ -131,7 +150,7 @@ VALUE qv_handle_user_agent_set(VALUE self, VALUE val)
|
|
131
150
|
typedef struct qv_supports_params_st
|
132
151
|
{
|
133
152
|
qv_handle_t *handle;
|
134
|
-
|
153
|
+
char *url;
|
135
154
|
QuviSupportsType type;
|
136
155
|
QuviSupportsMode mode;
|
137
156
|
QuviBoolean res;
|
@@ -140,22 +159,23 @@ typedef struct qv_supports_params_st
|
|
140
159
|
static void* qv_handle_supports_p_nogvl(void *data1)
|
141
160
|
{
|
142
161
|
qv_supports_params_t *params = data1;
|
143
|
-
params->res = quvi_supports(params->handle->q,
|
162
|
+
params->res = quvi_supports(params->handle->q, params->url,
|
144
163
|
params->mode, params->type);
|
145
164
|
return 0;
|
146
165
|
}
|
147
166
|
|
148
167
|
VALUE qv_handle_supports_p(int argc, VALUE *argv, VALUE self)
|
149
168
|
{
|
150
|
-
VALUE opts;
|
169
|
+
VALUE opts, url;
|
151
170
|
qv_supports_params_t params;
|
152
171
|
|
172
|
+
rb_scan_args(argc, argv, "11", &url, &opts);
|
173
|
+
|
153
174
|
params.handle = DATA_PTR(self);
|
154
175
|
params.type = QUVI_SUPPORTS_TYPE_ANY;
|
155
176
|
params.mode = QUVI_SUPPORTS_MODE_OFFLINE;
|
156
177
|
params.res = QUVI_FALSE;
|
157
|
-
|
158
|
-
Check_Type(params.url, T_STRING);
|
178
|
+
params.url = StringValueCStr(url);
|
159
179
|
if (opts != Qnil) {
|
160
180
|
VALUE arg;
|
161
181
|
Check_Type(opts, T_HASH);
|
@@ -174,7 +194,7 @@ VALUE qv_handle_supports_p(int argc, VALUE *argv, VALUE self)
|
|
174
194
|
} else if (arg == qv_sym_any) {
|
175
195
|
params.type = QUVI_SUPPORTS_TYPE_ANY;
|
176
196
|
} else {
|
177
|
-
rb_raise(rb_eArgError, "unknown type: %s",
|
197
|
+
rb_raise(rb_eArgError, "unknown type: %s", StringValueCStr(arg));
|
178
198
|
}
|
179
199
|
}
|
180
200
|
}
|
@@ -182,12 +202,184 @@ VALUE qv_handle_supports_p(int argc, VALUE *argv, VALUE self)
|
|
182
202
|
if (params.res == QUVI_TRUE) {
|
183
203
|
return Qtrue;
|
184
204
|
}
|
185
|
-
if (quvi_errcode(params.handle) != QUVI_ERROR_NO_SUPPORT) {
|
186
|
-
qv_raise(params.handle, "unable to check if URL supported");
|
205
|
+
if (quvi_errcode(params.handle->q) != QUVI_ERROR_NO_SUPPORT) {
|
206
|
+
qv_raise(params.handle, rb_sprintf("unable to check if URL supported (url=%s)", params.url));
|
187
207
|
}
|
188
208
|
return Qfalse;
|
189
209
|
}
|
190
210
|
|
211
|
+
VALUE qv_handle_each_script(VALUE self)
|
212
|
+
{
|
213
|
+
qv_handle_t *handle = DATA_PTR(self);
|
214
|
+
QuviScriptType types[] = {
|
215
|
+
QUVI_SCRIPT_TYPE_SCAN,
|
216
|
+
QUVI_SCRIPT_TYPE_PLAYLIST,
|
217
|
+
QUVI_SCRIPT_TYPE_MEDIA,
|
218
|
+
QUVI_SCRIPT_TYPE_SUBTITLE,
|
219
|
+
QUVI_SCRIPT_TYPE_SUBTITLE_EXPORT
|
220
|
+
};
|
221
|
+
VALUE type_names[] = {
|
222
|
+
rb_str_freeze(rb_external_str_new_cstr("scan")),
|
223
|
+
rb_str_freeze(rb_external_str_new_cstr("playlist")),
|
224
|
+
rb_str_freeze(rb_external_str_new_cstr("media")),
|
225
|
+
rb_str_freeze(rb_external_str_new_cstr("subtitle")),
|
226
|
+
rb_str_freeze(rb_external_str_new_cstr("subtitle_export"))
|
227
|
+
};
|
228
|
+
size_t i;
|
229
|
+
|
230
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
231
|
+
|
232
|
+
for (i = 0; i < sizeof(types) / sizeof(QuviScriptType); ++i) {
|
233
|
+
while (quvi_script_next(handle->q, types[i]) == QUVI_TRUE) {
|
234
|
+
VALUE script = rb_hash_new();
|
235
|
+
char *s;
|
236
|
+
|
237
|
+
#define set_property(key, id) \
|
238
|
+
s = NULL; \
|
239
|
+
quvi_script_get(handle->q, types[i], id, &s); \
|
240
|
+
if (s) { rb_hash_aset(script, key, rb_external_str_new_cstr(s)); }
|
241
|
+
set_property(qv_sym_sha1, QUVI_SCRIPT_PROPERTY_SHA1);
|
242
|
+
set_property(qv_sym_filepath, QUVI_SCRIPT_PROPERTY_FILEPATH);
|
243
|
+
rb_hash_aset(script, qv_sym_type, type_names[i]);
|
244
|
+
quvi_script_get(handle->q, types[i], QUVI_SCRIPT_PROPERTY_DOMAINS, &s);
|
245
|
+
if (strlen(s) > 0) {
|
246
|
+
VALUE domains = rb_external_str_new_cstr(s);
|
247
|
+
rb_hash_aset(script, qv_sym_domains, rb_str_split(domains, ","));
|
248
|
+
}
|
249
|
+
set_property(qv_sym_export_format, QUVI_SCRIPT_PROPERTY_EXPORT_FORMAT);
|
250
|
+
#undef set_property
|
251
|
+
|
252
|
+
rb_yield(script);
|
253
|
+
}
|
254
|
+
}
|
255
|
+
return Qnil;
|
256
|
+
}
|
257
|
+
|
258
|
+
typedef struct qv_media_new_params_st
|
259
|
+
{
|
260
|
+
qv_handle_t *handle;
|
261
|
+
char *url;
|
262
|
+
quvi_media_t res;
|
263
|
+
} qv_media_new_params_t;
|
264
|
+
|
265
|
+
static void* qv_media_new_nogvl(void *data1)
|
266
|
+
{
|
267
|
+
qv_media_new_params_t *params = data1;
|
268
|
+
params->res = quvi_media_new(params->handle->q, params->url);
|
269
|
+
return 0;
|
270
|
+
}
|
271
|
+
|
272
|
+
VALUE qv_handle_parse_media(VALUE self, VALUE url)
|
273
|
+
{
|
274
|
+
qv_media_new_params_t params;
|
275
|
+
VALUE media, streams, stream;
|
276
|
+
double d;
|
277
|
+
char *s, *best;
|
278
|
+
|
279
|
+
params.handle = DATA_PTR(self);
|
280
|
+
params.url = StringValueCStr(url);
|
281
|
+
|
282
|
+
rb_thread_call_without_gvl(qv_media_new_nogvl, ¶ms, RUBY_UBF_IO, 0);
|
283
|
+
if (quvi_ok(params.handle->q) == QUVI_FALSE) {
|
284
|
+
qv_raise(params.handle, rb_sprintf("unable create quvi_media_t handle (url=%s)", params.url));
|
285
|
+
}
|
286
|
+
media = rb_hash_new();
|
287
|
+
#define set_property_str(item, key, id) \
|
288
|
+
s = NULL; \
|
289
|
+
quvi_media_get(params.res, id, &s); \
|
290
|
+
if (s) { rb_hash_aset(item, key, rb_external_str_new_cstr(s)); }
|
291
|
+
#define set_property_int(item, key, id) \
|
292
|
+
d = -1; \
|
293
|
+
quvi_media_get(params.res, id, &d); \
|
294
|
+
if (d > 0) { rb_hash_aset(item, key, INT2NUM((int)d)); }
|
295
|
+
set_property_str(media, qv_sym_id, QUVI_MEDIA_PROPERTY_ID);
|
296
|
+
set_property_str(media, qv_sym_title, QUVI_MEDIA_PROPERTY_TITLE);
|
297
|
+
set_property_str(media, qv_sym_thumbnail_url, QUVI_MEDIA_PROPERTY_THUMBNAIL_URL);
|
298
|
+
set_property_int(media, qv_sym_start_time_ms, QUVI_MEDIA_PROPERTY_START_TIME_MS);
|
299
|
+
set_property_int(media, qv_sym_duration_ms, QUVI_MEDIA_PROPERTY_DURATION_MS);
|
300
|
+
streams = rb_hash_aset(media, qv_sym_streams, rb_ary_new());
|
301
|
+
quvi_media_stream_choose_best(params.res);
|
302
|
+
quvi_media_get(params.res, QUVI_MEDIA_STREAM_PROPERTY_ID, &best);
|
303
|
+
quvi_media_stream_reset(params.res);
|
304
|
+
while (quvi_media_stream_next(params.res) == QUVI_TRUE) {
|
305
|
+
stream = rb_hash_new();
|
306
|
+
set_property_str(stream, qv_sym_id, QUVI_MEDIA_STREAM_PROPERTY_ID);
|
307
|
+
if (strcmp(best, s) == 0) {
|
308
|
+
rb_hash_aset(stream, qv_sym_best, Qtrue);
|
309
|
+
}
|
310
|
+
set_property_int(stream, qv_sym_video_height, QUVI_MEDIA_STREAM_PROPERTY_VIDEO_HEIGHT);
|
311
|
+
set_property_int(stream, qv_sym_video_width, QUVI_MEDIA_STREAM_PROPERTY_VIDEO_WIDTH);
|
312
|
+
set_property_str(stream, qv_sym_video_encoding, QUVI_MEDIA_STREAM_PROPERTY_VIDEO_ENCODING);
|
313
|
+
set_property_int(stream, qv_sym_video_bitrate_kbit_s, QUVI_MEDIA_STREAM_PROPERTY_VIDEO_BITRATE_KBIT_S);
|
314
|
+
set_property_str(stream, qv_sym_audio_encoding, QUVI_MEDIA_STREAM_PROPERTY_AUDIO_ENCODING);
|
315
|
+
set_property_int(stream, qv_sym_audio_bitrate_kbit_s, QUVI_MEDIA_STREAM_PROPERTY_AUDIO_BITRATE_KBIT_S);
|
316
|
+
set_property_str(stream, qv_sym_container, QUVI_MEDIA_STREAM_PROPERTY_CONTAINER);
|
317
|
+
set_property_str(stream, qv_sym_url, QUVI_MEDIA_STREAM_PROPERTY_URL);
|
318
|
+
rb_ary_push(streams, stream);
|
319
|
+
}
|
320
|
+
|
321
|
+
#undef set_property_str
|
322
|
+
#undef set_property_int
|
323
|
+
quvi_media_free(params.res);
|
324
|
+
|
325
|
+
return media;
|
326
|
+
}
|
327
|
+
|
328
|
+
typedef struct qv_playlist_new_params_st
|
329
|
+
{
|
330
|
+
qv_handle_t *handle;
|
331
|
+
char *url;
|
332
|
+
quvi_playlist_t res;
|
333
|
+
} qv_playlist_new_params_t;
|
334
|
+
|
335
|
+
static void* qv_playlist_new_nogvl(void *data1)
|
336
|
+
{
|
337
|
+
qv_media_new_params_t *params = data1;
|
338
|
+
params->res = quvi_playlist_new(params->handle->q, params->url);
|
339
|
+
return 0;
|
340
|
+
}
|
341
|
+
|
342
|
+
VALUE qv_handle_parse_playlist(VALUE self, VALUE url)
|
343
|
+
{
|
344
|
+
qv_playlist_new_params_t params;
|
345
|
+
VALUE playlist, media, medium;
|
346
|
+
char *s;
|
347
|
+
double d;
|
348
|
+
|
349
|
+
params.handle = DATA_PTR(self);
|
350
|
+
params.url = StringValueCStr(url);
|
351
|
+
rb_thread_call_without_gvl(qv_playlist_new_nogvl, ¶ms, RUBY_UBF_IO, 0);
|
352
|
+
if (quvi_ok(params.handle->q) == QUVI_FALSE) {
|
353
|
+
qv_raise(params.handle, rb_sprintf("unable create quvi_media_t handle (url=%s)", params.url));
|
354
|
+
}
|
355
|
+
playlist = rb_hash_new();
|
356
|
+
#define set_property_str(item, key, id) \
|
357
|
+
s = NULL; \
|
358
|
+
quvi_playlist_get(params.res, id, &s); \
|
359
|
+
if (s) { rb_hash_aset(item, key, rb_external_str_new_cstr(s)); }
|
360
|
+
#define set_property_int(item, key, id) \
|
361
|
+
d = -1; \
|
362
|
+
quvi_playlist_get(params.res, id, &d); \
|
363
|
+
if (d > 0) { rb_hash_aset(item, key, INT2NUM((int)d)); }
|
364
|
+
|
365
|
+
set_property_str(playlist, qv_sym_id, QUVI_PLAYLIST_PROPERTY_ID);
|
366
|
+
set_property_str(playlist, qv_sym_title, QUVI_PLAYLIST_PROPERTY_TITLE);
|
367
|
+
set_property_str(playlist, qv_sym_thumbnail_url, QUVI_PLAYLIST_PROPERTY_THUMBNAIL_URL);
|
368
|
+
media = rb_hash_aset(playlist, qv_sym_media, rb_ary_new());
|
369
|
+
while (quvi_playlist_media_next(params.res) == QUVI_TRUE) {
|
370
|
+
medium = rb_hash_new();
|
371
|
+
set_property_str(medium, qv_sym_url, QUVI_PLAYLIST_MEDIA_PROPERTY_URL);
|
372
|
+
set_property_str(medium, qv_sym_title, QUVI_PLAYLIST_MEDIA_PROPERTY_TITLE);
|
373
|
+
set_property_int(medium, qv_sym_duration_ms, QUVI_PLAYLIST_MEDIA_PROPERTY_DURATION_MS);
|
374
|
+
rb_ary_push(media, medium);
|
375
|
+
}
|
376
|
+
#undef set_property_str
|
377
|
+
#undef set_property_int
|
378
|
+
|
379
|
+
quvi_playlist_free(params.res);
|
380
|
+
return playlist;
|
381
|
+
}
|
382
|
+
|
191
383
|
void init_quvi_handle()
|
192
384
|
{
|
193
385
|
qv_cHandle = rb_define_class_under(qv_mQuvi, "Handle", rb_cObject);
|
@@ -196,6 +388,9 @@ void init_quvi_handle()
|
|
196
388
|
rb_define_method(qv_cHandle, "supports?", qv_handle_supports_p, -1);
|
197
389
|
rb_define_method(qv_cHandle, "autoproxy=", qv_handle_autoproxy_set, 1);
|
198
390
|
rb_define_method(qv_cHandle, "user_agent=", qv_handle_user_agent_set, 1);
|
391
|
+
rb_define_method(qv_cHandle, "each_script", qv_handle_each_script, 0);
|
392
|
+
rb_define_method(qv_cHandle, "parse_media", qv_handle_parse_media, 1);
|
393
|
+
rb_define_method(qv_cHandle, "parse_playlist", qv_handle_parse_playlist, 1);
|
199
394
|
|
200
395
|
qv_DEFAULT_USER_AGENT = rb_const_get(qv_cHandle, rb_intern("DEFAULT_USER_AGENT"));
|
201
396
|
}
|
@@ -210,6 +405,25 @@ void init_symbols()
|
|
210
405
|
qv_sym_subtitle = ID2SYM(rb_intern("subtitle"));
|
211
406
|
qv_sym_type = ID2SYM(rb_intern("type"));
|
212
407
|
qv_sym_user_agent = ID2SYM(rb_intern("user_agent"));
|
408
|
+
qv_sym_export_format = ID2SYM(rb_intern("export_format"));
|
409
|
+
qv_sym_filepath = ID2SYM(rb_intern("filepath"));
|
410
|
+
qv_sym_domains = ID2SYM(rb_intern("domains"));
|
411
|
+
qv_sym_sha1 = ID2SYM(rb_intern("sha1"));
|
412
|
+
qv_sym_title = ID2SYM(rb_intern("title"));
|
413
|
+
qv_sym_id = ID2SYM(rb_intern("id"));
|
414
|
+
qv_sym_thumbnail_url = ID2SYM(rb_intern("thumbnail_url"));
|
415
|
+
qv_sym_start_time_ms = ID2SYM(rb_intern("start_time_ms"));
|
416
|
+
qv_sym_duration_ms = ID2SYM(rb_intern("duration_ms"));
|
417
|
+
qv_sym_video_height = ID2SYM(rb_intern("video_height"));
|
418
|
+
qv_sym_video_width = ID2SYM(rb_intern("video_width"));
|
419
|
+
qv_sym_video_encoding = ID2SYM(rb_intern("video_encoding"));
|
420
|
+
qv_sym_video_bitrate_kbit_s = ID2SYM(rb_intern("video_bitrate_kbit_s"));
|
421
|
+
qv_sym_audio_encoding = ID2SYM(rb_intern("audio_encoding"));
|
422
|
+
qv_sym_audio_bitrate_kbit_s = ID2SYM(rb_intern("audio_bitrate_kbit_s"));
|
423
|
+
qv_sym_container = ID2SYM(rb_intern("container"));
|
424
|
+
qv_sym_url = ID2SYM(rb_intern("url"));
|
425
|
+
qv_sym_streams = ID2SYM(rb_intern("streams"));
|
426
|
+
qv_sym_best = ID2SYM(rb_intern("best"));
|
213
427
|
}
|
214
428
|
|
215
429
|
void Init_quvi_ext()
|
data/lib/quvi.rb
CHANGED
@@ -2,3 +2,61 @@ require "quvi/version"
|
|
2
2
|
require "quvi/error"
|
3
3
|
require "quvi/handle"
|
4
4
|
require "quvi_ext"
|
5
|
+
|
6
|
+
require 'thread'
|
7
|
+
require 'monitor'
|
8
|
+
|
9
|
+
module Quvi
|
10
|
+
def self.parse(*urls)
|
11
|
+
options = urls.last.is_a?(Hash) ? urls.pop : {}
|
12
|
+
res = parse_multiple(urls, options)
|
13
|
+
urls.size == 1 ? res.first : res
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.parse_multiple(urls, options = {})
|
17
|
+
return [] if urls.empty?
|
18
|
+
num_threads = options.fetch(:threads) { 2 }
|
19
|
+
num_threads = [num_threads, urls.size].min
|
20
|
+
tasks = Queue.new
|
21
|
+
tasks.extend(MonitorMixin)
|
22
|
+
urls.each do |url|
|
23
|
+
tasks.push([:media, url])
|
24
|
+
tasks.push([:playlist, url])
|
25
|
+
end
|
26
|
+
tasks_tbd = tasks.size
|
27
|
+
done = tasks.new_cond
|
28
|
+
results = Queue.new
|
29
|
+
threads = Array.new(num_threads) do
|
30
|
+
Thread.new do
|
31
|
+
handle = Quvi::Handle.new(options)
|
32
|
+
loop do
|
33
|
+
type, url = tasks.pop
|
34
|
+
begin
|
35
|
+
if res = handle.parse(url, options.merge(:type => type))
|
36
|
+
results.push([url, res])
|
37
|
+
end
|
38
|
+
rescue Quvi::Error => ex
|
39
|
+
results.push([url, ex])
|
40
|
+
ensure
|
41
|
+
tasks.synchronize do
|
42
|
+
tasks_tbd -= 1
|
43
|
+
done.signal
|
44
|
+
break if tasks_tbd <= 0
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
tasks.synchronize do
|
51
|
+
done.wait_while do
|
52
|
+
tasks_tbd > 0
|
53
|
+
end
|
54
|
+
end if tasks_tbd > 0
|
55
|
+
res = []
|
56
|
+
until results.empty?
|
57
|
+
u, r = results.pop
|
58
|
+
res[urls.index(u)] = r
|
59
|
+
end
|
60
|
+
res
|
61
|
+
end
|
62
|
+
end
|
data/lib/quvi/handle.rb
CHANGED
@@ -2,6 +2,16 @@ module Quvi
|
|
2
2
|
class Handle
|
3
3
|
DEFAULT_USER_AGENT = "Mozilla/5.0".freeze
|
4
4
|
|
5
|
-
attr_accessor :user_agent, :allow_cookies
|
5
|
+
attr_accessor :user_agent, :allow_cookies
|
6
|
+
|
7
|
+
def parse(url, options = {})
|
8
|
+
online = options.fetch(:online) { true }
|
9
|
+
type = options.fetch(:type) { true }
|
10
|
+
if supports?(url, :type => type, :online => online)
|
11
|
+
res = send("parse_#{type}", url)
|
12
|
+
res[:type] = type
|
13
|
+
res
|
14
|
+
end
|
15
|
+
end
|
6
16
|
end
|
7
|
-
end
|
17
|
+
end
|
data/lib/quvi/version.rb
CHANGED
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quvi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Avseyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.5'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
description: This is the wrapper for libquvi library, which allows to extract media
|
@@ -47,7 +47,7 @@ extensions:
|
|
47
47
|
- ext/quvi_ext/extconf.rb
|
48
48
|
extra_rdoc_files: []
|
49
49
|
files:
|
50
|
-
- .gitignore
|
50
|
+
- ".gitignore"
|
51
51
|
- Gemfile
|
52
52
|
- Guardfile
|
53
53
|
- LICENSE
|
@@ -72,17 +72,17 @@ require_paths:
|
|
72
72
|
- lib
|
73
73
|
required_ruby_version: !ruby/object:Gem::Requirement
|
74
74
|
requirements:
|
75
|
-
- -
|
75
|
+
- - ">="
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
requirements: []
|
84
84
|
rubyforge_project:
|
85
|
-
rubygems_version: 2.
|
85
|
+
rubygems_version: 2.2.2
|
86
86
|
signing_key:
|
87
87
|
specification_version: 4
|
88
88
|
summary: The library to parse the media stream properties.
|