summaryrefslogtreecommitdiff
path: root/src/modules/ethumb
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-12 01:15:45 +0000
committerGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-12 01:15:45 +0000
commit34f53151414bcdf44ec81e582b007f74da595694 (patch)
tree863058f0d94e9d39998774a375aa6d242d8714a4 /src/modules/ethumb
parentae51833bac7ba5f72bd40a96beb13081c8d573f6 (diff)
merge ethumb.
This one was a painful bitch. The edbus2 port was quite broken, mainly leaking eina_stringshare and also not adding the '\0' to the strings that are represented as bytearray (paths cannot be utf8 to avoid translations). Emotion plugin was also quite bogus and the video thumbnail as edje (animated) is not working yet due bug in Edje_Edit api -- someone needs to investigate this, seems strange. Emotion plugin also had a bug that it was deleting the object from inside object callback. Now it seems to work. Please report if it does not. SVN revision: 82675
Diffstat (limited to 'src/modules/ethumb')
-rw-r--r--src/modules/ethumb/emotion/emotion.c484
-rw-r--r--src/modules/ethumb/emotion/placeholder.pngbin0 -> 150 bytes
-rw-r--r--src/modules/ethumb/emotion/template.edc45
3 files changed, 529 insertions, 0 deletions
diff --git a/src/modules/ethumb/emotion/emotion.c b/src/modules/ethumb/emotion/emotion.c
new file mode 100644
index 0000000000..12750883d8
--- /dev/null
+++ b/src/modules/ethumb/emotion/emotion.c
@@ -0,0 +1,484 @@
1#include "Ethumb.h"
2#include "Ethumb_Plugin.h"
3
4#ifdef HAVE_CONFIG_H
5#include "config.h"
6#endif
7
8#define EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT 1
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <Eina.h>
13#include <Eet.h>
14#include <Ecore_File.h>
15#include <Evas.h>
16#include <Ecore.h>
17#include <Edje.h>
18#include <Edje_Edit.h>
19#include <Emotion.h>
20
21static Eina_Prefix *_pfx = NULL;
22static int _init_count = 0;
23static int _log_dom = -1;
24#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
25#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
26#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
27#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
28
29struct _emotion_plugin
30{
31 unsigned int fps;
32 double ptotal, len, pi;
33 double total_time, tmp_time;
34 unsigned int pcount;
35 unsigned int frnum;
36 Eina_Bool first;
37 Eet_File *ef;
38 Evas_Object *video;
39 Ethumb *e;
40 int w, h;
41};
42
43static Eina_Bool _frame_grab(void *data);
44static Eina_Bool _frame_grab_single(void *data);
45
46static void
47_resize_movie(struct _emotion_plugin *_plugin)
48{
49 Ethumb *e = _plugin->e;
50 double ratio;
51 int w, h;
52 int fx, fy, fw, fh;
53
54 ratio = emotion_object_ratio_get(_plugin->video);
55 ethumb_calculate_aspect_from_ratio(e, ratio, &w, &h);
56 ethumb_calculate_fill_from_ratio(e, ratio, &fx, &fy, &fw, &fh);
57 DBG("size: w=%d, h=%d fill: x=%d, y=%d, w=%d, h=%d", w, h, fx, fy, fw, fh);
58
59 _plugin->w = w;
60 _plugin->h = h;
61
62 ethumb_plugin_image_resize(e, _plugin->w, _plugin->h);
63
64 evas_object_resize(_plugin->video, fw, fh);
65 evas_object_move(_plugin->video, fx, fy);
66 emotion_object_audio_mute_set(_plugin->video, 1);
67}
68
69static void
70_frame_decode_cb(void *data, Evas_Object *o EINA_UNUSED, void *event_info EINA_UNUSED)
71{
72 struct _emotion_plugin *_plugin = data;
73
74 if (_plugin->ef)
75 _frame_grab(data);
76 else
77 _frame_grab_single(data);
78}
79
80static void
81_frame_resized_cb(void *data, Evas_Object *o EINA_UNUSED, void *event_info EINA_UNUSED)
82{
83 _resize_movie(data);
84}
85
86static void
87_video_stopped_cb(void *data, Evas_Object *o EINA_UNUSED, void *event_info EINA_UNUSED)
88{
89 struct _emotion_plugin *_plugin = data;
90
91 _plugin->pi = 0;
92 _plugin->ptotal = 0;
93 _plugin->first = EINA_FALSE;
94 _plugin->total_time = _plugin->tmp_time;
95}
96
97static void
98_video_pos_set(struct _emotion_plugin *_plugin)
99{
100 double pos;
101 double interval;
102
103 pos = ethumb_video_start_get(_plugin->e);
104 interval = ethumb_video_interval_get(_plugin->e);
105 _plugin->len = emotion_object_play_length_get(_plugin->video);
106
107 if (_plugin->len > 0)
108 _plugin->first = EINA_TRUE;
109
110 if (pos <=0 || pos >= 1)
111 _plugin->pi = 0.1 * _plugin->len + _plugin->pcount *
112 _plugin->len * interval;
113 else
114 _plugin->pi = pos * _plugin->len + _plugin->pcount *
115 _plugin->len * interval;
116
117 emotion_object_position_set(_plugin->video, _plugin->pi);
118}
119
120static int
121_setup_thumbnail(struct _emotion_plugin *_plugin)
122{
123 char buf[4096];
124 Evas *evas;
125 Evas_Object *edje;
126 unsigned int i;
127 const char *thumb_path;
128
129 ethumb_thumb_path_get(_plugin->e, &thumb_path, NULL);
130 evas = ethumb_evas_get(_plugin->e);
131
132 if (!edje_file_group_exists(thumb_path, "movie/thumb"))
133 {
134 ERR("no group 'movie/thumb' found in file=%s", thumb_path);
135 goto exit_error;
136 }
137
138 edje = edje_edit_object_add(evas);
139 edje_object_file_set(edje, thumb_path, "movie/thumb");
140 if (!edje_object_part_exists(edje, "image"))
141 {
142 ERR("no 'image' part found in file=%s, group=movie/thumb", thumb_path);
143 evas_object_del(edje);
144 goto exit_error;
145 }
146 if (!edje_edit_program_exist(edje, "animate"))
147 {
148 ERR("no 'animate' program found in file=%s, group=movie/thumb",
149 thumb_path);
150 evas_object_del(edje);
151 goto exit_error;
152 }
153
154 for (i = 0; i < _plugin->frnum; i++)
155 {
156 snprintf(buf, sizeof(buf), "images/%d", i);
157 edje_edit_image_data_add(edje, buf, i);
158 if (i == 0)
159 edje_edit_state_image_set(edje, "image", "default", 0.00, buf);
160 else
161 edje_edit_state_tween_add(edje, "image", "default", 0.00, buf);
162 }
163
164 edje_edit_program_transition_time_set(edje, "animate",
165 _plugin->total_time);
166 edje_edit_program_transition_time_set(edje, "animate_loop",
167 _plugin->total_time);
168 edje_edit_group_min_w_set(edje, _plugin->w);
169 edje_edit_group_max_w_set(edje, _plugin->w);
170 edje_edit_group_min_h_set(edje, _plugin->h);
171 edje_edit_group_max_h_set(edje, _plugin->h);
172 edje_edit_save(edje);
173
174 evas_object_del(edje);
175
176 return 1;
177
178exit_error:
179 return 0;
180}
181
182static void
183_finish_thumb_obj(void *data)
184{
185 struct _emotion_plugin *_plugin = data;
186 evas_object_del(_plugin->video);
187 free(_plugin);
188}
189
190static void
191_finish_thumb_generation(struct _emotion_plugin *_plugin, int success)
192{
193 int r = 0;
194
195 evas_object_smart_callback_del(_plugin->video, "frame_resize",
196 _frame_resized_cb);
197 evas_object_smart_callback_del(_plugin->video, "frame_decode",
198 _frame_decode_cb);
199 evas_object_smart_callback_del(_plugin->video, "decode_stop",
200 _video_stopped_cb);
201
202 emotion_object_play_set(_plugin->video, 0);
203
204 if (_plugin->ef)
205 {
206 Eet_Error err = eet_close(_plugin->ef);
207 if (err != EET_ERROR_NONE)
208 {
209 ERR("Error writing Eet thumbnail file: %d", err);
210 success = EINA_FALSE;
211 }
212 }
213
214 if (success)
215 r = _setup_thumbnail(_plugin);
216
217 ethumb_finished_callback_call(_plugin->e, r);
218
219 ecore_job_add(_finish_thumb_obj, _plugin);
220}
221
222static Eina_Bool
223_frame_grab_single(void *data)
224{
225 struct _emotion_plugin *_plugin = data;
226 Ethumb *e = _plugin->e;
227 double p;
228
229 if (_plugin->len <= 0)
230 {
231 _video_pos_set(_plugin);
232 return EINA_TRUE;
233 }
234
235 p = emotion_object_position_get(_plugin->video);
236// if (p < _plugin->pi)
237 if (p <= 0.0)
238 return EINA_TRUE;
239
240 DBG("saving static thumbnail at position=%f (intended=%f)", p, _plugin->pi);
241
242 ethumb_image_save(e);
243
244 evas_object_smart_callback_del(_plugin->video, "frame_resize",
245 _frame_resized_cb);
246 emotion_object_play_set(_plugin->video, 0);
247 evas_object_del(_plugin->video);
248 free(_plugin);
249
250 ethumb_finished_callback_call(e, 1);
251
252 return EINA_FALSE;
253}
254
255static Eina_Bool
256_frame_grab(void *data)
257{
258 struct _emotion_plugin *_plugin = data;
259 Ethumb *e = _plugin->e;
260 char buf[4096];
261 const void *pixels;
262 double p;
263
264 if (_plugin->len <= 0)
265 {
266 _video_pos_set(_plugin);
267 return EINA_TRUE;
268 }
269
270 p = emotion_object_position_get(_plugin->video);
271 if (p < _plugin->pi)
272 return EINA_TRUE;
273
274 if (_plugin->first)
275 {
276 _plugin->pi = p;
277 _plugin->first = EINA_FALSE;
278 }
279
280 if (p > _plugin->pi + _plugin->ptotal)
281 {
282 _plugin->total_time += _plugin->tmp_time;
283 if (_plugin->pcount >= ethumb_video_ntimes_get(e))
284 {
285 _finish_thumb_generation(_plugin, EINA_TRUE);
286 return EINA_FALSE;
287 }
288 else
289 {
290 _plugin->pcount++;
291 _video_pos_set(_plugin);
292 return EINA_TRUE;
293 }
294 }
295
296 _plugin->tmp_time = p - _plugin->pi;
297
298 if (_plugin->ef)
299 {
300 Ecore_Evas *ee = ethumb_ecore_evas_get(e);
301 int quality, compress;
302
303 quality = ethumb_thumb_quality_get(e);
304 compress = ethumb_thumb_compress_get(e);
305
306 pixels = ecore_evas_buffer_pixels_get(ee);
307 snprintf(buf, sizeof(buf), "images/%d", _plugin->frnum);
308 eet_data_image_write(_plugin->ef, buf, pixels, _plugin->w, _plugin->h,
309 0, compress, quality, quality);
310 _plugin->frnum++;
311 }
312
313 return EINA_TRUE;
314}
315
316static void
317_generate_animated_thumb(struct _emotion_plugin *_plugin)
318{
319 const char *thumb_path;
320 char *thumb_dir;
321 char buf[4096];
322 Ethumb *e = _plugin->e;
323
324 snprintf(buf, sizeof(buf),
325 "%s/ethumb/modules/emotion/" MODULE_ARCH "/template.edj",
326 eina_prefix_lib_get(_pfx));
327 ethumb_thumb_path_get(e, &thumb_path, NULL);
328 thumb_dir = ecore_file_dir_get(thumb_path);
329 ecore_file_mkpath(thumb_dir);
330 free(thumb_dir);
331 if (!eina_file_copy(buf, thumb_path, 0, NULL, NULL))
332 {
333 ERR("Couldn't copy file '%s' to '%s'", buf, thumb_path);
334 ERR("could not open '%s'", thumb_path);
335 _finish_thumb_generation(_plugin, 0);
336 return;
337 }
338 _plugin->ef = eet_open(thumb_path, EET_FILE_MODE_READ_WRITE);
339 if (!_plugin->ef)
340 {
341 ERR("could not open '%s'", thumb_path);
342 _finish_thumb_generation(_plugin, 0);
343 }
344}
345
346static void *
347_thumb_generate(Ethumb *e)
348{
349 Evas_Object *o;
350 int r;
351 const char *file;
352 Ethumb_Thumb_Format f;
353 struct _emotion_plugin *_plugin = calloc(sizeof(struct _emotion_plugin), 1);
354
355 o = emotion_object_add(ethumb_evas_get(e));
356 r = emotion_object_init(o, NULL);
357 if (!r)
358 {
359 ERR("Could not initialize emotion object.");
360 evas_object_del(o);
361 ethumb_finished_callback_call(e, 0);
362 free(_plugin);
363 return NULL;
364 }
365
366 _plugin->video = o;
367
368 ethumb_file_get(e, &file, NULL);
369 f = ethumb_thumb_format_get(e);
370
371 emotion_object_file_set(o, file);
372 emotion_object_audio_mute_set(o, EINA_TRUE);
373
374 _plugin->video = o;
375 _plugin->e = e;
376
377 _plugin->ptotal = ethumb_video_time_get(e) / ethumb_video_ntimes_get(e);
378 _plugin->pcount = 1;
379
380 _resize_movie(_plugin);
381 evas_object_smart_callback_add(o, "frame_decode",
382 _frame_decode_cb, _plugin);
383 evas_object_smart_callback_add(o, "frame_resize",
384 _frame_resized_cb, _plugin);
385 evas_object_smart_callback_add(o, "decode_stop",
386 _video_stopped_cb, _plugin);
387
388 if (f == ETHUMB_THUMB_EET)
389 {
390 _generate_animated_thumb(_plugin);
391 }
392
393 _video_pos_set(_plugin);
394 emotion_object_play_set(o, 1);
395 evas_object_show(o);
396
397 return _plugin;
398}
399
400static void
401_thumb_cancel(Ethumb *e EINA_UNUSED, void *data)
402{
403 struct _emotion_plugin *_plugin = data;
404
405 if (_plugin->ef) eet_close(_plugin->ef);
406 evas_object_del(_plugin->video);
407 free(_plugin);
408}
409
410EAPI Ethumb_Plugin *
411ethumb_plugin_get(void)
412{
413 static const char *extensions[] = { "avi", "mp4", "ogv", "mov", "mpg", "wmv",
414 NULL };
415 static Ethumb_Plugin plugin =
416 {
417 extensions,
418 _thumb_generate,
419 _thumb_cancel
420 };
421
422 return &plugin;
423}
424
425static Eina_Bool
426_module_init(void)
427{
428 if (_init_count > 0)
429 {
430 _init_count++;
431 return EINA_TRUE;
432 }
433
434 _log_dom = eina_log_domain_register("ethumb_emotion", EINA_COLOR_GREEN);
435 if (_log_dom < 0)
436 {
437 EINA_LOG_ERR("Could not register log domain: ethumb_emotion");
438 goto error_log;
439 }
440
441 _pfx = eina_prefix_new(NULL, ethumb_init,
442 "ETHUMB", "ethumb", "checkme",
443 PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
444 PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
445 if (!_pfx)
446 {
447 ERR("Could not get ethumb installation prefix.");
448 goto error_pfx;
449 }
450
451 emotion_init();
452
453 _init_count = 1;
454 return EINA_TRUE;
455
456 error_pfx:
457 eina_log_domain_unregister(_log_dom);
458 _log_dom = -1;
459
460 error_log:
461 return EINA_FALSE;
462}
463
464static void
465_module_shutdown(void)
466{
467 if (_init_count <= 0)
468 {
469 EINA_LOG_ERR("Init count not greater than 0 in shutdown.");
470 return;
471 }
472 _init_count--;
473 if (_init_count > 0) return;
474
475 emotion_shutdown();
476
477 eina_prefix_free(_pfx);
478 _pfx = NULL;
479 eina_log_domain_unregister(_log_dom);
480 _log_dom = -1;
481}
482
483EINA_MODULE_INIT(_module_init);
484EINA_MODULE_SHUTDOWN(_module_shutdown);
diff --git a/src/modules/ethumb/emotion/placeholder.png b/src/modules/ethumb/emotion/placeholder.png
new file mode 100644
index 0000000000..2c90acdc92
--- /dev/null
+++ b/src/modules/ethumb/emotion/placeholder.png
Binary files differ
diff --git a/src/modules/ethumb/emotion/template.edc b/src/modules/ethumb/emotion/template.edc
new file mode 100644
index 0000000000..050641c12f
--- /dev/null
+++ b/src/modules/ethumb/emotion/template.edc
@@ -0,0 +1,45 @@
1collections {
2
3 group {
4 name: "movie/thumb";
5
6 images.image: "placeholder.png" COMP;
7
8 parts {
9 part {
10 name: "image";
11 type: IMAGE;
12 mouse_events: 0;
13 description {
14 state: "default" 0.0;
15 fill.smooth: 0;
16 image.normal: "placeholder.png"; /* edje doesn't allow image without files anymore */
17 }
18 }
19 }
20
21 programs {
22 program {
23 name: "animate";
24 signal: "animate";
25 action: STATE_SET "default" 0.0;
26 transition: LINEAR 3.0;
27 target: "image";
28 }
29 program {
30 name: "animate_loop";
31 signal: "animate_loop";
32 action: STATE_SET "default" 0.0;
33 transition: LINEAR 3.0;
34 target: "image";
35 after: "animate_loop";
36 }
37 program {
38 name: "animate_stop";
39 signal: "animate_stop";
40 action: ACTION_STOP;
41 target: "animate_loop";
42 }
43 }
44 }
45}