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