remove old vlc, fix build bugs and introduce m4 for generic players.
[profile/ivi/emotion.git] / src / modules / generic / emotion_generic.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <sys/mman.h>
5 #include <sys/stat.h>
6 #include <sys/time.h>
7 #include <sys/types.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <Eina.h>
11 #include <Evas.h>
12
13 #include "Emotion.h"
14 #include "emotion_private.h"
15 #include "emotion_generic.h"
16
17 static Eina_Prefix *pfx = NULL;
18
19 static int _emotion_generic_log_domain = -1;
20 #define DBG(...) EINA_LOG_DOM_DBG(_emotion_generic_log_domain, __VA_ARGS__)
21 #define INF(...) EINA_LOG_DOM_INFO(_emotion_generic_log_domain, __VA_ARGS__)
22 #define WRN(...) EINA_LOG_DOM_WARN(_emotion_generic_log_domain, __VA_ARGS__)
23 #define ERR(...) EINA_LOG_DOM_ERR(_emotion_generic_log_domain, __VA_ARGS__)
24 #define CRITICAL(...) EINA_LOG_DOM_CRIT(_emotion_generic_log_domain, __VA_ARGS__)
25
26
27 struct _default_players {
28    const char *name;
29    const char *cmdline;
30 };
31
32 static struct _default_players players[] = {
33 #ifdef EMOTION_BUILD_GENERIC_VLC
34        { "vlc", "em_generic_vlc" },
35 #endif
36        { NULL, NULL }
37 };
38
39 static const char *
40 _get_player(const char *name)
41 {
42    const char *selected_name = NULL;
43    const char *libdir = eina_prefix_lib_get(pfx);
44    static char buf[PATH_MAX];
45    int i;
46
47    if (name)
48      {
49         for (i = 0; players[i].name; i++)
50           {
51              if (!strcmp(players[i].name, name))
52                {
53                   selected_name = players[i].cmdline;
54                   break;
55                }
56           }
57      }
58
59    if ((!selected_name) && (name))
60      selected_name = name;
61
62    if (selected_name)
63      {
64         const char *cmd;
65
66         if (selected_name[0] == '/') cmd = selected_name;
67         else
68           {
69              snprintf(buf, sizeof(buf), "%s/emotion/utils/%s",
70                       libdir, selected_name);
71              cmd = buf;
72           }
73
74         DBG("Try generic player '%s'", cmd);
75         if (access(cmd, R_OK | X_OK) == 0)
76           {
77              INF("Using generic player '%s'", cmd);
78              return cmd;
79           }
80      }
81
82    for (i = 0; players[i].name; i++)
83      {
84         snprintf(buf, sizeof(buf), "%s/emotion/utils/%s",
85                  libdir, players[i].cmdline);
86         DBG("Try generic player '%s'", buf);
87         if (access(buf, R_OK | X_OK) == 0)
88           {
89              INF("Using fallback player '%s'", buf);
90              return buf;
91           }
92      }
93
94    ERR("no generic player found, given name='%s'", name ? name : "");
95    return NULL;
96 }
97
98 static void
99 _player_send_cmd(Emotion_Generic_Video *ev, int cmd)
100 {
101    if (cmd >= EM_CMD_LAST)
102      {
103         ERR("invalid command to player.");
104         return;
105      }
106    ecore_exe_send(ev->player.exe, &cmd, sizeof(cmd));
107 }
108
109 static void
110 _player_send_int(Emotion_Generic_Video *ev, int number)
111 {
112    ecore_exe_send(ev->player.exe, &number, sizeof(number));
113 }
114
115 static void
116 _player_send_float(Emotion_Generic_Video *ev, float number)
117 {
118    ecore_exe_send(ev->player.exe, &number, sizeof(number));
119 }
120
121 static void
122 _player_send_str(Emotion_Generic_Video *ev, const char *str, Eina_Bool stringshared)
123 {
124    int len;
125
126    if (stringshared)
127      len = eina_stringshare_strlen(str) + 1;
128    else
129      len = strlen(str) + 1;
130    ecore_exe_send(ev->player.exe, &len, sizeof(len));
131    ecore_exe_send(ev->player.exe, str, len);
132 }
133
134 static Eina_Bool
135 _create_shm_data(Emotion_Generic_Video *ev, const char *shmname)
136 {
137    int shmfd;
138    int npages;
139    size_t size;
140    Emotion_Generic_Video_Shared *vs;
141
142    shmfd = shm_open(shmname, O_CREAT | O_RDWR | O_TRUNC, 0777);
143    size = 3 * (ev->w * ev->h * DEFAULTPITCH) + sizeof(*vs);
144
145    npages = (int)(size / getpagesize()) + 1;
146    size = npages * getpagesize();
147
148    if (ftruncate(shmfd, size))
149      {
150         ERR("error when allocating shared memory (size = %zd): "
151             "%s", size, strerror(errno));
152         return EINA_FALSE;
153      }
154    vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0);
155    if (vs == MAP_FAILED)
156      {
157         ERR("error when mapping shared memory.\n");
158         return EINA_FALSE;
159      }
160
161    vs->size = size;
162    vs->width = ev->w;
163    vs->height = ev->h;
164    vs->pitch = DEFAULTPITCH;
165    vs->frame.emotion = 0;
166    vs->frame.player = 1;
167    vs->frame.last = 2;
168    vs->frame.next = 2;
169    sem_init(&vs->lock, 1, 1);
170    ev->frame.frames[0] = (unsigned char *)vs + sizeof(*vs);
171    ev->frame.frames[1] = (unsigned char *)vs + sizeof(*vs) + vs->height * vs->width * vs->pitch;
172    ev->frame.frames[2] = (unsigned char *)vs + sizeof(*vs) + 2 * vs->height * vs->width * vs->pitch;
173
174    if (ev->shared)
175      munmap(ev->shared, ev->shared->size);
176    ev->shared = vs;
177
178    return EINA_TRUE;
179 }
180
181 static void
182 _player_new_frame(Emotion_Generic_Video *ev)
183 {
184    if (!ev->drop++)
185      _emotion_frame_new(ev->obj);
186 }
187
188 static void
189 _player_file_set_done(Emotion_Generic_Video *ev)
190 {
191    if (!_create_shm_data(ev, ev->shmname))
192      {
193         ERR("could not create shared memory.");
194         return;
195      }
196    _player_send_cmd(ev, EM_CMD_FILE_SET_DONE);
197 }
198
199 static void
200 _file_open(Emotion_Generic_Video *ev)
201 {
202    INF("Opening file: %s", ev->filename);
203    ev->w = DEFAULTWIDTH;
204    ev->h = DEFAULTHEIGHT;
205    ev->ratio = (double)DEFAULTWIDTH / DEFAULTHEIGHT;
206    ev->speed = 1.0;
207    ev->len = 0;
208    ev->drop = 0;
209
210    if (!ev->ready)
211      return;
212    _player_send_cmd(ev, EM_CMD_FILE_SET);
213    _player_send_str(ev, ev->filename, EINA_TRUE);
214 }
215
216 static void
217 _player_ready(Emotion_Generic_Video *ev)
218 {
219    INF("received: player ready.");
220
221    ev->initializing = EINA_FALSE;
222    ev->ready = EINA_TRUE;
223
224    if (!ev->filename)
225      return;
226
227    _file_open(ev);
228 }
229
230 #define RCV_CMD_PARAM(src, param) \
231    memcpy(&(param), (src), sizeof((param))); \
232    (src) = (char *)(src) + sizeof((param));
233
234 #define RCV_CMD_STR(src, buf, len) \
235    RCV_CMD_PARAM((src), (len)); \
236    memcpy((buf), (src), (len)); \
237    (src) = (char *)(src) + len;
238
239 static int
240 _player_int_read(Emotion_Generic_Video *ev __UNUSED__, void **data)
241 {
242    int number;
243    memcpy(&number, *data, sizeof(number));
244    *data = (char *)(*data) + sizeof(number);
245
246    return number;
247 }
248
249 static void
250 _player_frame_resize(Emotion_Generic_Video *ev, void *line)
251 {
252    int w, h;
253    RCV_CMD_PARAM(line, w);
254    RCV_CMD_PARAM(line, h);
255
256    INF("received frame resize: %dx%d", w, h);
257    ev->w = w;
258    ev->h = h;
259    ev->ratio = (float)w / h;
260
261    if (ev->opening)
262      return;
263
264    _emotion_frame_resize(ev->obj, ev->w, ev->h, ev->ratio);
265 }
266
267 static void
268 _player_length_changed(Emotion_Generic_Video *ev, void *line)
269 {
270    float length;
271    RCV_CMD_PARAM(line, length);
272
273    INF("received length changed: %0.3f", length);
274
275    ev->len = length;
276    _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
277 }
278
279 static void
280 _player_position_changed(Emotion_Generic_Video *ev, void *line)
281 {
282    float position;
283    RCV_CMD_PARAM(line, position);
284
285    INF("received position changed: %0.3f", position);
286
287    ev->pos = position;
288    _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
289
290    if (ev->len == 0)
291      return;
292
293    float progress = ev->pos / ev->len;
294    char buf[16];
295    snprintf(buf, sizeof(buf), "%0.1f%%", progress * 100);
296
297    _emotion_progress_set(ev->obj, buf, progress);
298 }
299
300 static void
301 _player_seekable_changed(Emotion_Generic_Video *ev, void *line)
302 {
303    int seekable;
304    RCV_CMD_PARAM(line, seekable);
305
306    INF("received seekable changed: %d", seekable);
307
308    seekable = !!seekable;
309
310    ev->seekable = seekable;
311 }
312
313 static void
314 _player_volume(Emotion_Generic_Video *ev, void *line)
315 {
316    float vol, oldvol;
317    RCV_CMD_PARAM(line, vol);
318
319    INF("received volume: %0.3f", vol);
320
321    oldvol = ev->volume;
322    ev->volume = vol;
323    if (vol != oldvol && !ev->opening)
324      _emotion_audio_level_change(ev->obj);
325 }
326
327 static void
328 _player_audio_mute(Emotion_Generic_Video *ev, void *line)
329 {
330    int mute;
331    RCV_CMD_PARAM(line, mute);
332
333    INF("received audio mute: %d", mute);
334
335    ev->audio_mute = !!mute;
336 }
337
338 static void
339 _audio_channels_free(Emotion_Generic_Video *ev)
340 {
341    int i;
342    for (i = 0; i < ev->audio_channels_count; i++)
343      eina_stringshare_del(ev->audio_channels[i].name);
344    free(ev->audio_channels);
345    ev->audio_channels_count = 0;
346 }
347
348 static void
349 _player_audio_tracks_info(Emotion_Generic_Video *ev, void *line)
350 {
351    int track_current, tracks_count;
352    int i;
353
354    if (ev->audio_channels_count)
355      _audio_channels_free(ev);
356
357    RCV_CMD_PARAM(line, track_current);
358    RCV_CMD_PARAM(line, tracks_count);
359    INF("video with %d audio tracks (current = %d):", tracks_count, track_current);
360    ev->audio_channels = calloc(
361       tracks_count, sizeof(Emotion_Generic_Audio_Channel));
362    ev->audio_channels_count = tracks_count;
363    ev->audio_channel_current = track_current;
364    for (i = 0; i < tracks_count; i++)
365      {
366         int tid, len;
367         char buf[PATH_MAX];
368         RCV_CMD_PARAM(line, tid);
369         RCV_CMD_STR(line, buf, len);
370         ev->audio_channels[i].id = tid;
371         ev->audio_channels[i].name = eina_stringshare_add_length(buf, len);
372         INF("\t%d: %s", tid, buf);
373      }
374 }
375
376 static void
377 _player_file_closed(Emotion_Generic_Video *ev)
378 {
379    INF("Closed previous file.");
380    sem_destroy(&ev->shared->lock);
381
382    ev->closing = EINA_FALSE;
383
384    if (ev->opening)
385      _file_open(ev);
386 }
387
388 static void
389 _player_open_done(Emotion_Generic_Video *ev)
390 {
391    ev->opening = EINA_FALSE;
392    shm_unlink(ev->shmname);
393    _emotion_open_done(ev->obj);
394
395    if (ev->play)
396      {
397         _player_send_cmd(ev, EM_CMD_PLAY);
398         _player_send_float(ev, ev->pos);
399      }
400
401    INF("Open done");
402 }
403
404 static void
405 _player_read_cmd(Emotion_Generic_Video *ev, void *line, int size __UNUSED__)
406 {
407    int type;
408    RCV_CMD_PARAM(line, type);
409
410    switch (type) {
411       case EM_RESULT_INIT:
412          _player_ready(ev);
413          break;
414       case EM_RESULT_FRAME_NEW:
415          _player_new_frame(ev);
416          break;
417       case EM_RESULT_FILE_SET:
418          _player_file_set_done(ev);
419          break;
420       case EM_RESULT_FILE_SET_DONE:
421          _player_open_done(ev);
422          break;
423       case EM_RESULT_FILE_CLOSE:
424          _player_file_closed(ev);
425          break;
426       case EM_RESULT_PLAYBACK_STOPPED:
427          _emotion_playback_finished(ev->obj);
428          break;
429       case EM_RESULT_FRAME_SIZE:
430          _player_frame_resize(ev, line);
431          break;
432       case EM_RESULT_LENGTH_CHANGED:
433          _player_length_changed(ev, line);
434          break;
435       case EM_RESULT_POSITION_CHANGED:
436          _player_position_changed(ev, line);
437          break;
438       case EM_RESULT_SEEKABLE_CHANGED:
439          _player_seekable_changed(ev, line);
440          break;
441       case EM_RESULT_AUDIO_TRACK_INFO:
442          _player_audio_tracks_info(ev, line);
443          break;
444       default:
445          WRN("received wrong command: %d", type);
446    };
447 }
448
449 #undef RCV_CMD_PARAM
450
451 static Eina_Bool
452 _player_data_cb(void *data, int type __UNUSED__, void *event)
453 {
454    Ecore_Exe_Event_Data *ev = event;
455    Emotion_Generic_Video *evideo = data;
456    int i;
457
458    if (ev->exe != evideo->player.exe)
459      {
460         ERR("slave != ev->exe");
461         return ECORE_CALLBACK_DONE;
462      }
463
464    if (ev->size < 4)
465      {
466         ERR("invalid command: missing bytes.");
467         return ECORE_CALLBACK_DONE;
468      }
469
470    for (i = 0; ev->lines[i].line; i++)
471      _player_read_cmd(evideo, ev->lines[i].line, ev->lines[i].size);
472
473    return ECORE_CALLBACK_DONE;
474 }
475
476 static Eina_Bool
477 _player_add_cb(void *data, int type __UNUSED__, void *event)
478 {
479    Ecore_Exe_Event_Add *event_add = event;
480    Ecore_Exe *player = event_add->exe;
481    Emotion_Generic_Video *ev = data;
482
483    if (ev->player.exe != player)
484      {
485         ERR("ev->player != player.");
486         return ECORE_CALLBACK_DONE;
487      }
488
489    _player_send_cmd(ev, EM_CMD_INIT);
490    _player_send_str(ev, ev->shmname, EINA_TRUE);
491
492    return ECORE_CALLBACK_DONE;
493 }
494
495 static Eina_Bool
496 _player_del_cb(void *data, int type __UNUSED__, void *event __UNUSED__)
497 {
498    Emotion_Generic_Video *ev = data;
499    ERR("player died.");
500
501    ev->player.exe = NULL;
502    ev->ready = EINA_FALSE;
503    _emotion_decode_stop(ev->obj);
504
505    return ECORE_CALLBACK_DONE;
506 }
507
508 static Eina_Bool
509 _fork_and_exec(Evas_Object *obj __UNUSED__, Emotion_Generic_Video *ev)
510 {
511    char shmname[256];
512    struct timeval tv;
513
514    gettimeofday(&tv, NULL);
515    snprintf(shmname, sizeof(shmname), "/em-generic-shm_%d_%d",
516             (int)tv.tv_sec, (int)tv.tv_usec);
517
518    ev->shmname = eina_stringshare_add(shmname);
519
520    ev->player_add = ecore_event_handler_add(
521       ECORE_EXE_EVENT_ADD, _player_add_cb, ev);
522    ev->player_del = ecore_event_handler_add(
523       ECORE_EXE_EVENT_DEL, _player_del_cb, ev);
524    ev->player_data = ecore_event_handler_add(
525       ECORE_EXE_EVENT_DATA, _player_data_cb, ev);
526
527    ev->player.exe = ecore_exe_pipe_run(
528       ev->cmdline,
529       ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE |
530       ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER,
531       ev);
532
533    if (!ev->player.exe)
534      {
535         ERR("could not start player.");
536         return EINA_FALSE;
537      }
538
539    ev->initializing = EINA_TRUE;
540
541    return EINA_TRUE;
542 }
543
544 static unsigned char
545 em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
546 {
547    Emotion_Generic_Video *ev;
548    const char *player;
549
550    if (!emotion_video) return 0;
551    player = _get_player(opt ? opt->player : NULL);
552    if (!player) return 0;
553
554    ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev));
555    if (!ev) return 0;
556
557    ev->speed = 1.0;
558    ev->volume = 0.5;
559    ev->audio_mute = EINA_FALSE;
560
561    ev->obj = obj;
562    ev->cmdline = eina_stringshare_add(player);
563    *emotion_video = ev;
564
565    return _fork_and_exec(obj, ev);
566 }
567
568 static int
569 em_shutdown(void *data)
570 {
571    Emotion_Generic_Video *ev = data;
572
573    if (!ev) return 0;
574
575    if (ev->player.exe)
576      {
577         ecore_exe_terminate(ev->player.exe);
578         ecore_exe_free(ev->player.exe);
579         ev->player.exe = NULL;
580      }
581
582    if (ev->shared)
583      munmap(ev->shared, ev->shared->size);
584
585    _audio_channels_free(ev);
586
587    eina_stringshare_del(ev->cmdline);
588    eina_stringshare_del(ev->shmname);
589
590    ecore_event_handler_del(ev->player_add);
591    ecore_event_handler_del(ev->player_data);
592    ecore_event_handler_del(ev->player_del);
593
594    return 1;
595 }
596
597 static unsigned char
598 em_file_open(const char *file, Evas_Object *obj __UNUSED__, void *data)
599 {
600    Emotion_Generic_Video *ev = data;
601    INF("file set: %s", file);
602    if (!ev) return 0;
603
604    ev->pos = 0;
605    ev->opening = EINA_TRUE;
606
607    eina_stringshare_replace(&ev->filename, file);
608
609    if (!ev->closing)
610      _file_open(ev);
611
612    return 1;
613 }
614
615 static void
616 em_file_close(void *data)
617 {
618    Emotion_Generic_Video *ev = data;
619
620    if (!ev) return;
621    INF("file close: %s", ev->filename);
622
623    if (!ev->filename)
624      return;
625
626    _player_send_cmd(ev, EM_CMD_FILE_CLOSE);
627    ev->closing = EINA_TRUE;
628 }
629
630 static Emotion_Format
631 em_format_get(void *ef __UNUSED__)
632 {
633    return EMOTION_FORMAT_BGRA;
634 }
635
636 static void
637 em_video_data_size_get(void *data, int *w, int *h)
638 {
639    Emotion_Generic_Video *ev = data;
640
641    if (!ev) return;
642    if (w) *w = ev->w;
643    if (h) *h = ev->h;
644 }
645
646 static void
647 em_play(void *data, double pos)
648 {
649    Emotion_Generic_Video *ev = data;
650
651    if (!ev)
652      return;
653
654    ev->play = EINA_TRUE;
655    INF("play: %0.3f", pos);
656
657    if (ev->initializing || ev->opening)
658      return;
659
660    if (ev->ready)
661      {
662         _player_send_cmd(ev, EM_CMD_PLAY);
663         _player_send_float(ev, ev->pos);
664         return;
665      }
666
667    ev->player.exe = ecore_exe_pipe_run(
668       ev->cmdline,
669       ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE |
670       ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER,
671       ev);
672
673    if (!ev->player.exe)
674      ERR("could not start player.");
675 }
676
677 static void
678 em_stop(void *data)
679 {
680    Emotion_Generic_Video *ev = data;
681
682    if (!ev)
683      return;
684
685    ev->play = EINA_FALSE;
686
687    if (!ev->ready)
688      return;
689
690    _player_send_cmd(ev, EM_CMD_STOP);
691    _emotion_decode_stop(ev->obj);
692 }
693
694 static void
695 em_size_get(void *data, int *w, int *h)
696 {
697    Emotion_Generic_Video *ev = data;
698    if(w) *w = ev->w;
699    if(h) *h = ev->h;
700 }
701
702 static void
703 em_pos_set(void *data, double pos)
704 {
705    Emotion_Generic_Video *ev = data;
706    float position = pos;
707    _player_send_cmd(ev, EM_CMD_POSITION_SET);
708    _player_send_float(ev, position);
709    _emotion_seek_done(ev->obj);
710 }
711
712 static double
713 em_len_get(void *data)
714 {
715    Emotion_Generic_Video *ev = data;
716    return ev->len;
717 }
718
719 static int
720 em_fps_num_get(void *data)
721 {
722    Emotion_Generic_Video *ev = data;
723    return (int)(ev->fps * 1000.0);
724 }
725
726 static int
727 em_fps_den_get(void *ef __UNUSED__)
728 {
729    return 1000;
730 }
731
732 static double
733 em_fps_get(void *data)
734 {
735    Emotion_Generic_Video *ev = data;
736    return ev->fps;
737 }
738
739 static double
740 em_pos_get(void *data)
741 {
742    Emotion_Generic_Video *ev = data;
743    return ev->pos;
744 }
745
746 static void
747 em_vis_set(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
748 {
749 }
750
751 static Emotion_Vis
752 em_vis_get(void *data)
753 {
754    Emotion_Generic_Video *ev = data;
755    return ev->vis;
756 }
757
758 static Eina_Bool
759 em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
760 {
761    return EINA_FALSE;
762 }
763
764 static double
765 em_ratio_get(void *data)
766 {
767    Emotion_Generic_Video *ev = data;
768    return ev->ratio;
769 }
770
771 static int em_video_handled(void *ef __UNUSED__)
772 {
773    fprintf(stderr, "video handled!\n");
774    return 1;
775 }
776
777 static int em_audio_handled(void *ef __UNUSED__)
778 {
779    fprintf(stderr, "audio handled!\n");
780    return 1;
781 }
782
783 static int em_seekable(void *data)
784 {
785    Emotion_Generic_Video *ev = data;
786    return ev->seekable;
787 }
788
789 static void em_frame_done(void *ef __UNUSED__)
790 {
791 }
792
793 static int
794 em_yuv_rows_get(void *data __UNUSED__, int w __UNUSED__, int h __UNUSED__, unsigned char **yrows __UNUSED__, unsigned char **urows __UNUSED__, unsigned char **vrows __UNUSED__)
795 {
796    return 0;
797 }
798
799 static int
800 em_bgra_data_get(void *data, unsigned char **bgra_data)
801 {
802    Emotion_Generic_Video *ev = data;
803
804    if (!ev || ev->opening || ev->closing)
805      return 0;
806
807    // lock frame here
808    sem_wait(&ev->shared->lock);
809
810    // send current frame to emotion
811    if (ev->shared->frame.emotion != ev->shared->frame.last)
812      {
813         ev->shared->frame.next = ev->shared->frame.emotion;
814         ev->shared->frame.emotion = ev->shared->frame.last;
815      }
816    *bgra_data = ev->frame.frames[ev->shared->frame.emotion];
817
818    // unlock frame here
819    sem_post(&ev->shared->lock);
820    ev->drop = 0;
821
822    return 1;
823 }
824
825 static void
826 em_event_feed(void *ef __UNUSED__, int event __UNUSED__)
827 {
828 }
829
830 static void
831 em_event_mouse_button_feed(void *ef __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__)
832 {
833 }
834
835 static void
836 em_event_mouse_move_feed(void *ef __UNUSED__, int x __UNUSED__, int y __UNUSED__)
837 {
838 }
839
840 static int
841 em_video_channel_count(void *ef __UNUSED__)
842 {
843    int ret  = 0;
844    return ret;
845 }
846
847 static void
848 em_video_channel_set(void *ef __UNUSED__, int channel __UNUSED__)
849 {
850 }
851
852 static int
853 em_video_channel_get(void *ef __UNUSED__)
854 {
855    return 1;
856 }
857
858 static const char *
859 em_video_channel_name_get(void *ef __UNUSED__, int channel __UNUSED__)
860 {
861    return NULL;
862 }
863
864 static void
865 em_video_channel_mute_set(void *ef __UNUSED__, int mute __UNUSED__)
866 {
867 }
868
869 static int
870 em_video_channel_mute_get(void *data)
871 {
872    Emotion_Generic_Video *ev = data;
873    return ev->video_mute;
874 }
875
876 static int
877 em_audio_channel_count(void *data)
878 {
879    Emotion_Generic_Video *ev = data;
880    return ev->audio_channels_count;
881 }
882
883 static void
884 em_audio_channel_set(void *data, int channel)
885 {
886    Emotion_Generic_Video *ev = data;
887    int i;
888
889    for (i = 0; i < ev->audio_channels_count; i++)
890      {
891         if (ev->audio_channels[i].id == channel)
892           {
893              _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET);
894              _player_send_int(ev, channel);
895              break;
896           }
897      }
898 }
899
900 static int
901 em_audio_channel_get(void *data)
902 {
903    Emotion_Generic_Video *ev = data;
904    return ev->audio_channel_current;
905 }
906
907 static const char *
908 em_audio_channel_name_get(void *data, int channel)
909 {
910    Emotion_Generic_Video *ev = data;
911    int i;
912
913    for (i = 0; i < ev->audio_channels_count; i++)
914      {
915         if (ev->audio_channels[i].id == channel)
916           return ev->audio_channels[i].name;
917      }
918
919    return NULL;
920 }
921
922 static void
923 em_audio_channel_mute_set(void *data, int mute)
924 {
925    Emotion_Generic_Video *ev = data;
926    _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
927    _player_send_int(ev, mute);
928    ev->audio_mute = !!mute;
929 }
930
931 static int
932 em_audio_channel_mute_get(void *data)
933 {
934    Emotion_Generic_Video *ev = data;
935    return ev->audio_mute;
936 }
937
938 static void
939 em_audio_channel_volume_set(void *data, double vol)
940 {
941    Emotion_Generic_Video *ev = data;
942    float fvol;
943
944    if (vol > 1.0) vol = 1.0;
945    if (vol < 0.0) vol = 0.0;
946
947    fvol = vol;
948    _player_send_cmd(ev, EM_CMD_VOLUME_SET);
949    _player_send_float(ev, fvol);
950
951    ev->volume = vol;
952 }
953
954 static double
955 em_audio_channel_volume_get(void *data)
956 {
957    Emotion_Generic_Video *ev = data;
958    return ev->volume;
959 }
960
961 static int
962 em_spu_channel_count(void *ef __UNUSED__)
963 {
964    return 0;
965 }
966
967 static void
968 em_spu_channel_set(void *ef __UNUSED__, int channel __UNUSED__)
969 {
970 }
971
972 static int
973 em_spu_channel_get(void *ef __UNUSED__)
974 {
975    int num = 0;
976    return num;
977 }
978
979 static const char *
980 em_spu_channel_name_get(void *ef __UNUSED__, int channel __UNUSED__)
981 {
982    return NULL;
983 }
984
985 static void
986 em_spu_channel_mute_set(void *ef __UNUSED__, int mute __UNUSED__)
987 {
988    return;
989 }
990
991 static int
992 em_spu_channel_mute_get(void *ef __UNUSED__)
993 {
994    return 0;
995 }
996
997 static int
998 em_chapter_count(void *ef __UNUSED__)
999 {
1000    int num = 0;
1001    return num;
1002 }
1003
1004 static void
1005 em_chapter_set(void *ef __UNUSED__, int chapter __UNUSED__)
1006 {
1007 }
1008
1009 static int
1010 em_chapter_get(void *ef __UNUSED__)
1011 {
1012    int num = 0;
1013    return num;
1014 }
1015
1016 static const char *
1017 em_chapter_name_get(void *ef __UNUSED__, int chapter __UNUSED__)
1018 {
1019    return NULL;
1020 }
1021
1022 static void
1023 em_speed_set(void *data, double speed)
1024 {
1025    Emotion_Generic_Video *ev = data;
1026    float rate = speed;
1027
1028    _player_send_cmd(ev, EM_CMD_SPEED_SET);
1029    _player_send_float(ev, rate);
1030
1031    ev->speed = rate;
1032 }
1033
1034 static double
1035 em_speed_get(void *data)
1036 {
1037    Emotion_Generic_Video *ev = data;
1038    return (double)ev->speed;
1039 }
1040
1041 static int
1042 em_eject(void *ef __UNUSED__)
1043 {
1044    return 1;
1045 }
1046
1047 static const char *
1048 em_meta_get(void *ef __UNUSED__, int meta __UNUSED__)
1049 {
1050    char * meta_data = NULL;
1051    return meta_data;
1052 }
1053
1054 static Emotion_Video_Module em_module =
1055 {
1056    em_init, /* init */
1057    em_shutdown, /* shutdown */
1058    em_file_open, /* file_open */
1059    em_file_close, /* file_close */
1060    em_play, /* play */
1061    em_stop, /* stop */
1062    em_size_get, /* size_get */
1063    em_pos_set, /* pos_set */
1064    em_len_get, /* len_get */
1065    em_fps_num_get, /* fps_num_get */
1066    em_fps_den_get, /* fps_den_get */
1067    em_fps_get, /* fps_get */
1068    em_pos_get, /* pos_get */
1069    em_vis_set, /* vis_set */
1070    em_vis_get, /* vis_get */
1071    em_vis_supported, /* vis_supported */
1072    em_ratio_get, /* ratio_get */
1073    em_video_handled, /* video_handled */
1074    em_audio_handled, /* audio_handled */
1075    em_seekable, /* seekable */
1076    em_frame_done, /* frame_done */
1077    em_format_get, /* format_get */
1078    em_video_data_size_get, /* video_data_size_get */
1079    em_yuv_rows_get, /* yuv_rows_get */
1080    em_bgra_data_get, /* bgra_data_get */
1081    em_event_feed, /* event_feed */
1082    em_event_mouse_button_feed, /* event_mouse_button_feed */
1083    em_event_mouse_move_feed, /* event_mouse_move_feed */
1084    em_video_channel_count, /* video_channel_count */
1085    em_video_channel_set, /* video_channel_set */
1086    em_video_channel_get, /* video_channel_get */
1087    em_video_channel_name_get, /* video_channel_name_get */
1088    em_video_channel_mute_set, /* video_channel_mute_set */
1089    em_video_channel_mute_get, /* video_channel_mute_get */
1090    em_audio_channel_count, /* audio_channel_count */
1091    em_audio_channel_set, /* audio_channel_set */
1092    em_audio_channel_get, /* audio_channel_get */
1093    em_audio_channel_name_get, /* audio_channel_name_get */
1094    em_audio_channel_mute_set, /* audio_channel_mute_set */
1095    em_audio_channel_mute_get, /* audio_channel_mute_get */
1096    em_audio_channel_volume_set, /* audio_channel_volume_set */
1097    em_audio_channel_volume_get, /* audio_channel_volume_get */
1098    em_spu_channel_count, /* spu_channel_count */
1099    em_spu_channel_set, /* spu_channel_set */
1100    em_spu_channel_get, /* spu_channel_get */
1101    em_spu_channel_name_get, /* spu_channel_name_get */
1102    em_spu_channel_mute_set, /* spu_channel_mute_set */
1103    em_spu_channel_mute_get, /* spu_channel_mute_get */
1104    em_chapter_count, /* chapter_count */
1105    em_chapter_set, /* chapter_set */
1106    em_chapter_get, /* chapter_get */
1107    em_chapter_name_get, /* chapter_name_get */
1108    em_speed_set, /* speed_set */
1109    em_speed_get, /* speed_get */
1110    em_eject, /* eject */
1111    em_meta_get, /* meta_get */
1112    NULL /* handle */
1113 };
1114
1115 static Eina_Bool
1116 module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
1117 {
1118    if (!module) {
1119         return EINA_FALSE;
1120    }
1121
1122    if (_emotion_generic_log_domain < 0)
1123      {
1124         eina_threads_init();
1125         eina_log_threads_enable();
1126         _emotion_generic_log_domain = eina_log_domain_register
1127           ("emotion-generic", EINA_COLOR_LIGHTCYAN);
1128         if (_emotion_generic_log_domain < 0)
1129           {
1130              EINA_LOG_CRIT("Could not register log domain 'emotion-generic'");
1131              return EINA_FALSE;
1132           }
1133      }
1134
1135
1136    if (!em_module.init(obj, video, opt))        {
1137         return EINA_FALSE;
1138    }
1139
1140    *module = &em_module;
1141
1142    return EINA_TRUE;
1143 }
1144
1145 static void module_close(Emotion_Video_Module *module __UNUSED__, void *video)
1146 {
1147         em_module.shutdown(video);
1148 }
1149
1150
1151 static Eina_Bool
1152 generic_module_init(void)
1153 {
1154    if (!pfx)
1155      {
1156         pfx = eina_prefix_new(NULL, emotion_object_add,
1157                               "EMOTION", "emotion", NULL,
1158                               PACKAGE_BIN_DIR,
1159                               PACKAGE_LIB_DIR,
1160                               PACKAGE_DATA_DIR,
1161                               "");
1162         if (!pfx) return EINA_FALSE;
1163      }
1164    return _emotion_module_register("generic", module_open, module_close);
1165 }
1166
1167 static void
1168 generic_module_shutdown(void)
1169 {
1170    if (pfx)
1171      {
1172         eina_prefix_free(pfx);
1173         pfx = NULL;
1174      }
1175    _emotion_module_unregister("generic");
1176 }
1177
1178 #ifndef EMOTION_STATIC_BUILD_GENERIC
1179
1180 EINA_MODULE_INIT(generic_module_init);
1181 EINA_MODULE_SHUTDOWN(generic_module_shutdown);
1182
1183 #endif
1184