14 #include "emotion_private.h"
15 #include "emotion_generic.h"
17 static Eina_Prefix *pfx = NULL;
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__)
27 struct _default_players {
32 static struct _default_players players[] = {
33 #ifdef EMOTION_BUILD_GENERIC_VLC
34 { "vlc", "em_generic_vlc" },
40 _get_player(const char *name)
42 const char *selected_name = NULL;
43 const char *libdir = eina_prefix_lib_get(pfx);
44 static char buf[PATH_MAX];
49 for (i = 0; players[i].name; i++)
51 if (!strcmp(players[i].name, name))
53 selected_name = players[i].cmdline;
59 if ((!selected_name) && (name))
66 if (selected_name[0] == '/') cmd = selected_name;
69 snprintf(buf, sizeof(buf), "%s/emotion/utils/%s",
70 libdir, selected_name);
74 DBG("Try generic player '%s'", cmd);
75 if (access(cmd, R_OK | X_OK) == 0)
77 INF("Using generic player '%s'", cmd);
82 for (i = 0; players[i].name; i++)
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)
89 INF("Using fallback player '%s'", buf);
94 ERR("no generic player found, given name='%s'", name ? name : "");
99 _player_send_cmd(Emotion_Generic_Video *ev, int cmd)
101 if (cmd >= EM_CMD_LAST)
103 ERR("invalid command to player.");
106 write(ev->fd_write, &cmd, sizeof(cmd));
110 _player_send_int(Emotion_Generic_Video *ev, int number)
112 write(ev->fd_write, &number, sizeof(number));
116 _player_send_float(Emotion_Generic_Video *ev, float number)
118 write(ev->fd_write, &number, sizeof(number));
122 _player_send_str(Emotion_Generic_Video *ev, const char *str, Eina_Bool stringshared)
127 len = eina_stringshare_strlen(str) + 1;
129 len = strlen(str) + 1;
130 write(ev->fd_write, &len, sizeof(len));
131 write(ev->fd_write, str, len);
135 _create_shm_data(Emotion_Generic_Video *ev, const char *shmname)
140 Emotion_Generic_Video_Shared *vs;
142 shmfd = shm_open(shmname, O_CREAT | O_RDWR | O_TRUNC, 0777);
145 ERR("player: could not open shm: %s", shmname);
146 ERR("player: %s", strerror(errno));
149 size = 3 * (ev->w * ev->h * DEFAULTPITCH) + sizeof(*vs);
151 npages = (int)(size / getpagesize()) + 1;
152 size = npages * getpagesize();
154 if (ftruncate(shmfd, size))
156 ERR("error when allocating shared memory (size = %zd): "
157 "%s", size, strerror(errno));
161 vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0);
162 if (vs == MAP_FAILED)
164 ERR("error when mapping shared memory.\n");
171 vs->pitch = DEFAULTPITCH;
172 vs->frame.emotion = 0;
173 vs->frame.player = 1;
177 sem_init(&vs->lock, 1, 1);
178 ev->frame.frames[0] = (unsigned char *)vs + sizeof(*vs);
179 ev->frame.frames[1] = (unsigned char *)vs + sizeof(*vs) + vs->height * vs->width * vs->pitch;
180 ev->frame.frames[2] = (unsigned char *)vs + sizeof(*vs) + 2 * vs->height * vs->width * vs->pitch;
183 munmap(ev->shared, ev->shared->size);
190 _player_new_frame(Emotion_Generic_Video *ev)
194 _emotion_frame_new(ev->obj);
198 _file_open(Emotion_Generic_Video *ev)
200 INF("Opening file: %s", ev->filename);
203 if (!ev->ready || !ev->filename)
205 _player_send_cmd(ev, EM_CMD_FILE_SET);
206 _player_send_str(ev, ev->filename, EINA_TRUE);
210 _player_file_set_done(Emotion_Generic_Video *ev)
212 if (ev->file_changed)
215 ev->file_changed = EINA_FALSE;
219 if (!_create_shm_data(ev, ev->shmname))
221 ERR("could not create shared memory.");
224 _player_send_cmd(ev, EM_CMD_FILE_SET_DONE);
228 _player_ready(Emotion_Generic_Video *ev)
230 INF("received: player ready.");
232 ev->initializing = EINA_FALSE;
233 ev->ready = EINA_TRUE;
242 _em_read_safe(int fd, void *buf, ssize_t size)
254 r = read(fd, p, todo);
264 if (errno == EINTR || errno == EAGAIN)
268 ERR("could not read from fd %d: %s", fd, strerror(errno));
278 _player_cmd_param_read(Emotion_Generic_Video *ev, void *param, size_t size)
280 ssize_t done, todo, i;
282 /* When a parameter must be read, we cannot make sure it will be entirely
283 * available. Thus we store the bytes that could be read in a temp buffer,
284 * and when more data is read we try to complete the buffer and finally use
289 ev->cmd.tmp = malloc(size);
291 ev->cmd.total = size;
294 todo = ev->cmd.total - ev->cmd.i;
296 done = read(ev->fd_read, &ev->cmd.tmp[i], todo);
298 if (done < 0 && errno != EINTR && errno != EAGAIN)
305 ERR("problem when reading parameter from pipe.");
312 memcpy(param, ev->cmd.tmp, size);
325 _player_int_read(Emotion_Generic_Video *ev, int *i)
328 n = _em_read_safe(ev->fd_read, i, sizeof(*i));
331 ERR("could not read int from fd_read %d\n", ev->fd_read);
339 _player_str_read(Emotion_Generic_Video *ev, char *str, int *len)
343 if (!_player_int_read(ev, len))
346 n = _em_read_safe(ev->fd_read, str, *len);
349 ERR("could not read string from fd_read %d\n", ev->fd_read);
357 _player_frame_resize(Emotion_Generic_Video *ev)
361 w = ev->cmd.param.size.width;
362 h = ev->cmd.param.size.height;
364 INF("received frame resize: %dx%d", w, h);
367 ev->ratio = (float)w / h;
372 _emotion_frame_resize(ev->obj, ev->w, ev->h, ev->ratio);
376 _player_length_changed(Emotion_Generic_Video *ev)
378 float length = ev->cmd.param.f_num;
380 INF("received length changed: %0.3f", length);
383 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
387 _player_position_changed(Emotion_Generic_Video *ev)
389 float position = ev->cmd.param.f_num;
391 INF("received position changed: %0.3f", position);
394 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
399 float progress = ev->pos / ev->len;
401 snprintf(buf, sizeof(buf), "%0.1f%%", progress * 100);
403 _emotion_progress_set(ev->obj, buf, progress);
407 _player_seekable_changed(Emotion_Generic_Video *ev)
409 int seekable = ev->cmd.param.i_num;
411 INF("received seekable changed: %d", seekable);
413 seekable = !!seekable;
415 ev->seekable = seekable;
419 _player_volume(Emotion_Generic_Video *ev)
422 _player_float_read(ev, &vol);
424 INF("received volume: %0.3f", vol);
428 if (vol != oldvol && !ev->opening)
429 _emotion_audio_level_change(ev->obj);
433 _audio_channels_free(Emotion_Generic_Video *ev)
436 for (i = 0; i < ev->audio_channels_count; i++)
437 eina_stringshare_del(ev->audio_channels[i].name);
438 free(ev->audio_channels);
439 ev->audio_channels_count = 0;
443 _video_channels_free(Emotion_Generic_Video *ev)
446 for (i = 0; i < ev->video_channels_count; i++)
447 eina_stringshare_del(ev->video_channels[i].name);
448 free(ev->video_channels);
449 ev->video_channels_count = 0;
453 _spu_channels_free(Emotion_Generic_Video *ev)
456 for (i = 0; i < ev->spu_channels_count; i++)
457 eina_stringshare_del(ev->spu_channels[i].name);
458 free(ev->spu_channels);
459 ev->spu_channels_count = 0;
463 _player_tracks_info(Emotion_Generic_Video *ev, Emotion_Generic_Channel **channels, int *count, int *current)
465 Emotion_Generic_Channel *pchannels;
468 _player_int_read(ev, current);
469 _player_int_read(ev, count);
471 INF("number of tracks: %d (current = %d):", *count, *current);
472 pchannels = calloc(*count, sizeof(Emotion_Generic_Channel));
473 for (i = 0; i < *count; i++)
477 _player_int_read(ev, &tid);
478 _player_str_read(ev, buf, &len);
479 pchannels[i].id = tid;
480 pchannels[i].name = eina_stringshare_add_length(buf, len);
481 INF("\tchannel %d: %s", tid, buf);
484 *channels = pchannels;
488 _player_audio_tracks_info(Emotion_Generic_Video *ev)
490 INF("Receiving audio channels:");
491 if (ev->audio_channels_count)
492 _audio_channels_free(ev);
494 _player_tracks_info(ev, &ev->audio_channels, &ev->audio_channels_count,
495 &ev->audio_channel_current);
499 _player_video_tracks_info(Emotion_Generic_Video *ev)
501 INF("Receiving video channels:");
502 if (ev->video_channels_count)
503 _video_channels_free(ev);
505 _player_tracks_info(ev, &ev->video_channels, &ev->video_channels_count,
506 &ev->video_channel_current);
510 _player_spu_tracks_info(Emotion_Generic_Video *ev)
512 INF("Receiving spu channels:");
513 if (ev->spu_channels_count)
514 _spu_channels_free(ev);
516 _player_tracks_info(ev, &ev->spu_channels, &ev->spu_channels_count,
517 &ev->spu_channel_current);
521 _player_helper_str_read(Emotion_Generic_Video *ev, const char **pstr)
525 if (_player_str_read(ev, buf, &len))
526 *pstr = eina_stringshare_add_length(buf, len);
530 _player_meta_info_free(Emotion_Generic_Video *ev)
532 eina_stringshare_replace(&ev->meta.title, NULL);
533 eina_stringshare_replace(&ev->meta.artist, NULL);
534 eina_stringshare_replace(&ev->meta.album, NULL);
535 eina_stringshare_replace(&ev->meta.year, NULL);
536 eina_stringshare_replace(&ev->meta.genre, NULL);
537 eina_stringshare_replace(&ev->meta.comment, NULL);
538 eina_stringshare_replace(&ev->meta.disc_id, NULL);
539 eina_stringshare_replace(&ev->meta.count, NULL);
543 _player_meta_info_read(Emotion_Generic_Video *ev)
545 INF("Receiving meta info:");
546 _player_meta_info_free(ev);
547 _player_helper_str_read(ev, &ev->meta.title);
548 _player_helper_str_read(ev, &ev->meta.artist);
549 _player_helper_str_read(ev, &ev->meta.album);
550 _player_helper_str_read(ev, &ev->meta.year);
551 _player_helper_str_read(ev, &ev->meta.genre);
552 _player_helper_str_read(ev, &ev->meta.comment);
553 _player_helper_str_read(ev, &ev->meta.disc_id);
554 _player_helper_str_read(ev, &ev->meta.count);
555 INF("title: '%s'", ev->meta.title);
556 INF("artist: '%s'", ev->meta.artist);
557 INF("album: '%s'", ev->meta.album);
558 INF("year: '%s'", ev->meta.year);
559 INF("genre: '%s'", ev->meta.genre);
560 INF("comment: '%s'", ev->meta.comment);
561 INF("disc_id: '%s'", ev->meta.disc_id);
562 INF("count: '%s'", ev->meta.count);
566 _player_file_closed(Emotion_Generic_Video *ev)
568 INF("Closed previous file.");
569 sem_destroy(&ev->shared->lock);
571 ev->closing = EINA_FALSE;
578 _player_open_done(Emotion_Generic_Video *ev)
582 success = ev->cmd.param.i_num;
583 shm_unlink(ev->shmname);
585 if (ev->file_changed)
588 ev->file_changed = EINA_FALSE;
592 ev->opening = EINA_FALSE;
595 ERR("Could not open file.");
599 ev->file_ready = EINA_TRUE;
601 _emotion_open_done(ev->obj);
605 _player_send_cmd(ev, EM_CMD_PLAY);
606 _player_send_float(ev, ev->pos);
609 _player_send_cmd(ev, EM_CMD_VOLUME_SET);
610 _player_send_float(ev, ev->volume);
612 _player_send_cmd(ev, EM_CMD_SPEED_SET);
613 _player_send_float(ev, ev->speed);
615 int mute = ev->audio_mute;
616 _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
617 _player_send_int(ev, mute);
619 mute = ev->video_mute;
620 _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
621 _player_send_int(ev, mute);
624 _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
625 _player_send_int(ev, mute);
631 _player_cmd_process(Emotion_Generic_Video *ev)
633 switch (ev->cmd.type) {
637 case EM_RESULT_FRAME_NEW:
638 _player_new_frame(ev);
640 case EM_RESULT_FILE_SET:
641 _player_file_set_done(ev);
643 case EM_RESULT_FILE_SET_DONE:
644 _player_open_done(ev);
646 case EM_RESULT_FILE_CLOSE:
647 _player_file_closed(ev);
649 case EM_RESULT_PLAYBACK_STOPPED:
650 _emotion_playback_finished(ev->obj);
652 case EM_RESULT_FRAME_SIZE:
653 _player_frame_resize(ev);
655 case EM_RESULT_LENGTH_CHANGED:
656 _player_length_changed(ev);
658 case EM_RESULT_POSITION_CHANGED:
659 _player_position_changed(ev);
661 case EM_RESULT_SEEKABLE_CHANGED:
662 _player_seekable_changed(ev);
664 case EM_RESULT_AUDIO_TRACK_INFO:
665 _player_audio_tracks_info(ev);
667 case EM_RESULT_VIDEO_TRACK_INFO:
668 _player_video_tracks_info(ev);
670 case EM_RESULT_SPU_TRACK_INFO:
671 _player_spu_tracks_info(ev);
673 case EM_RESULT_META_INFO:
674 _player_meta_info_read(ev);
677 WRN("received wrong command: %d", ev->cmd.type);
684 _player_cmd_single_int_process(Emotion_Generic_Video *ev)
686 if (!_player_cmd_param_read(ev, &ev->cmd.param.i_num, sizeof(ev->cmd.param.i_num)))
689 _player_cmd_process(ev);
693 _player_cmd_single_float_process(Emotion_Generic_Video *ev)
695 if (!_player_cmd_param_read(ev, &ev->cmd.param.f_num, sizeof(ev->cmd.param.f_num)))
698 _player_cmd_process(ev);
702 _player_cmd_double_int_process(Emotion_Generic_Video *ev)
706 if (ev->cmd.num_params == 0)
708 ev->cmd.num_params = 2;
709 ev->cmd.cur_param = 0;
710 ev->cmd.param.size.width = 0;
711 ev->cmd.param.size.height = 0;
714 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
717 if (ev->cmd.cur_param == 0)
718 ev->cmd.param.size.width = param;
720 ev->cmd.param.size.height = param;
723 if (ev->cmd.cur_param == ev->cmd.num_params)
724 _player_cmd_process(ev);
728 _player_cmd_read(Emotion_Generic_Video *ev)
730 if (ev->cmd.type < 0)
732 if (!_player_cmd_param_read(ev, &ev->cmd.type, sizeof(ev->cmd.type)))
735 ev->cmd.num_params = 0;
738 switch (ev->cmd.type) {
740 case EM_RESULT_FILE_SET:
741 case EM_RESULT_PLAYBACK_STOPPED:
742 case EM_RESULT_FILE_CLOSE:
743 case EM_RESULT_FRAME_NEW:
744 _player_cmd_process(ev);
746 case EM_RESULT_FILE_SET_DONE:
747 case EM_RESULT_SEEKABLE_CHANGED:
748 _player_cmd_single_int_process(ev);
750 case EM_RESULT_LENGTH_CHANGED:
751 case EM_RESULT_POSITION_CHANGED:
752 _player_cmd_single_float_process(ev);
754 case EM_RESULT_FRAME_SIZE:
755 _player_cmd_double_int_process(ev);
759 WRN("received wrong command: %d", ev->cmd.type);
765 _player_cmd_handler_cb(void *data, Ecore_Fd_Handler *fd_handler)
767 Emotion_Generic_Video *ev = data;
769 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
771 ERR("an error occurred on fd_read %d.", ev->fd_read);
772 return ECORE_CALLBACK_CANCEL;
775 _player_cmd_read(ev);
777 return ECORE_CALLBACK_RENEW;
781 _player_data_cb(void *data, int type __UNUSED__, void *event)
783 Ecore_Exe_Event_Data *ev = event;
784 Emotion_Generic_Video *evideo = data;
787 if (ev->exe != evideo->player.exe)
789 ERR("slave != ev->exe");
790 return ECORE_CALLBACK_DONE;
793 for (i = 0; ev->lines[i].line; i++)
794 INF("received input from player: \"%s\"", ev->lines[i].line);
796 return ECORE_CALLBACK_DONE;
800 _player_add_cb(void *data, int type __UNUSED__, void *event)
802 Ecore_Exe_Event_Add *event_add = event;
803 Ecore_Exe *player = event_add->exe;
804 Emotion_Generic_Video *ev = data;
806 if (ev->player.exe != player)
808 ERR("ev->player != player.");
809 return ECORE_CALLBACK_DONE;
812 _player_send_cmd(ev, EM_CMD_INIT);
813 _player_send_str(ev, ev->shmname, EINA_TRUE);
815 return ECORE_CALLBACK_DONE;
819 _player_del_cb(void *data, int type __UNUSED__, void *event __UNUSED__)
821 Emotion_Generic_Video *ev = data;
824 ev->player.exe = NULL;
825 ev->ready = EINA_FALSE;
826 ev->file_ready = EINA_FALSE;
827 ecore_main_fd_handler_del(ev->fd_handler);
832 _emotion_decode_stop(ev->obj);
834 return ECORE_CALLBACK_DONE;
838 _player_exec(Emotion_Generic_Video *ev)
844 if (pipe(pipe_out) == -1)
846 ERR("could not create pipe for communication emotion -> player: %s", strerror(errno));
850 if (pipe(pipe_in) == -1)
852 ERR("could not create pipe for communication player -> emotion: %s", strerror(errno));
858 snprintf(buf, sizeof(buf), "%s %d %d\n", ev->cmdline, pipe_out[0], pipe_in[1]);
860 ev->player.exe = ecore_exe_pipe_run(
862 ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE |
863 ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER,
866 INF("created pipe emotion -> player: %d -> %d\n", pipe_out[1], pipe_out[0]);
867 INF("created pipe player -> emotion: %d -> %d\n", pipe_in[1], pipe_in[0]);
879 ev->fd_read = pipe_in[0];
880 ev->fd_write = pipe_out[1];
882 ev->fd_handler = ecore_main_fd_handler_add(
883 ev->fd_read, ECORE_FD_READ | ECORE_FD_ERROR, _player_cmd_handler_cb, ev,
890 _fork_and_exec(Evas_Object *obj, Emotion_Generic_Video *ev)
895 gettimeofday(&tv, NULL);
896 snprintf(shmname, sizeof(shmname), "/em-generic-shm_%d_%d",
897 (int)tv.tv_sec, (int)tv.tv_usec);
899 ev->shmname = eina_stringshare_add(shmname);
901 ev->player_add = ecore_event_handler_add(
902 ECORE_EXE_EVENT_ADD, _player_add_cb, ev);
903 ev->player_del = ecore_event_handler_add(
904 ECORE_EXE_EVENT_DEL, _player_del_cb, ev);
905 ev->player_data = ecore_event_handler_add(
906 ECORE_EXE_EVENT_DATA, _player_data_cb, ev);
909 if (!_player_exec(ev))
911 ERR("could not start player.");
915 ev->initializing = EINA_TRUE;
921 em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
923 Emotion_Generic_Video *ev;
926 if (!emotion_video) return 0;
927 player = _get_player(opt ? opt->player : NULL);
928 if (!player) return 0;
930 ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev));
937 ev->audio_mute = EINA_FALSE;
941 ev->cmdline = eina_stringshare_add(player);
944 return _fork_and_exec(obj, ev);
948 em_shutdown(void *data)
950 Emotion_Generic_Video *ev = data;
956 ecore_exe_terminate(ev->player.exe);
957 ecore_exe_free(ev->player.exe);
958 ev->player.exe = NULL;
962 munmap(ev->shared, ev->shared->size);
964 if (ev->fd_read >= 0)
966 if (ev->fd_write >= 0)
969 ecore_main_fd_handler_del(ev->fd_handler);
971 eina_stringshare_del(ev->cmdline);
972 eina_stringshare_del(ev->shmname);
974 ecore_event_handler_del(ev->player_add);
975 ecore_event_handler_del(ev->player_data);
976 ecore_event_handler_del(ev->player_del);
982 em_file_open(const char *file, Evas_Object *obj __UNUSED__, void *data)
984 Emotion_Generic_Video *ev = data;
985 INF("file set: %s", file);
988 eina_stringshare_replace(&ev->filename, file);
996 if (ev->ready && ev->opening)
998 INF("file changed while opening.");
999 ev->file_changed = EINA_TRUE;
1003 ev->opening = EINA_TRUE;
1012 em_file_close(void *data)
1014 Emotion_Generic_Video *ev = data;
1016 if (!ev || !ev->filename) return;
1018 INF("file close: %s", ev->filename);
1020 eina_stringshare_replace(&ev->filename, NULL);
1022 ev->file_ready = EINA_FALSE;
1023 _audio_channels_free(ev);
1024 _video_channels_free(ev);
1025 _spu_channels_free(ev);
1026 _player_meta_info_free(ev);
1031 _player_send_cmd(ev, EM_CMD_FILE_CLOSE);
1032 ev->closing = EINA_TRUE;
1035 static Emotion_Format
1036 em_format_get(void *ef __UNUSED__)
1038 return EMOTION_FORMAT_BGRA;
1042 em_video_data_size_get(void *data, int *w, int *h)
1044 Emotion_Generic_Video *ev = data;
1052 em_play(void *data, double pos)
1054 Emotion_Generic_Video *ev = data;
1059 ev->play = EINA_TRUE;
1060 INF("play: %0.3f", pos);
1062 if (ev->initializing || ev->opening)
1067 _player_send_cmd(ev, EM_CMD_PLAY);
1068 _player_send_float(ev, ev->pos);
1072 if (!_player_exec(ev))
1073 ERR("could not start player.");
1079 Emotion_Generic_Video *ev = data;
1084 ev->play = EINA_FALSE;
1086 if (!ev->file_ready)
1089 _player_send_cmd(ev, EM_CMD_STOP);
1090 _emotion_decode_stop(ev->obj);
1094 em_size_get(void *data, int *w, int *h)
1096 Emotion_Generic_Video *ev = data;
1102 em_pos_set(void *data, double pos)
1104 Emotion_Generic_Video *ev = data;
1105 float position = pos;
1107 if (!ev->file_ready)
1110 _player_send_cmd(ev, EM_CMD_POSITION_SET);
1111 _player_send_float(ev, position);
1112 _emotion_seek_done(ev->obj);
1116 em_len_get(void *data)
1118 Emotion_Generic_Video *ev = data;
1123 em_fps_num_get(void *data)
1125 Emotion_Generic_Video *ev = data;
1126 return (int)(ev->fps * 1000.0);
1130 em_fps_den_get(void *ef __UNUSED__)
1136 em_fps_get(void *data)
1138 Emotion_Generic_Video *ev = data;
1143 em_pos_get(void *data)
1145 Emotion_Generic_Video *ev = data;
1150 em_vis_set(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
1155 em_vis_get(void *data)
1157 Emotion_Generic_Video *ev = data;
1162 em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
1168 em_ratio_get(void *data)
1170 Emotion_Generic_Video *ev = data;
1174 static int em_video_handled(void *ef __UNUSED__)
1176 fprintf(stderr, "video handled!\n");
1180 static int em_audio_handled(void *ef __UNUSED__)
1182 fprintf(stderr, "audio handled!\n");
1186 static int em_seekable(void *data)
1188 Emotion_Generic_Video *ev = data;
1189 return ev->seekable;
1192 static void em_frame_done(void *ef __UNUSED__)
1197 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__)
1203 em_bgra_data_get(void *data, unsigned char **bgra_data)
1205 Emotion_Generic_Video *ev = data;
1207 if (!ev || !ev->file_ready)
1211 sem_wait(&ev->shared->lock);
1213 // send current frame to emotion
1214 if (ev->shared->frame.emotion != ev->shared->frame.last)
1216 ev->shared->frame.next = ev->shared->frame.emotion;
1217 ev->shared->frame.emotion = ev->shared->frame.last;
1219 *bgra_data = ev->frame.frames[ev->shared->frame.emotion];
1221 if (ev->shared->frame_drop > 1)
1222 WRN("dropped frames: %d", ev->shared->frame_drop - 1);
1223 ev->shared->frame_drop = 0;
1225 // unlock frame here
1226 sem_post(&ev->shared->lock);
1233 em_event_feed(void *ef __UNUSED__, int event __UNUSED__)
1238 em_event_mouse_button_feed(void *ef __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1243 em_event_mouse_move_feed(void *ef __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1248 em_video_channel_count(void *data)
1250 Emotion_Generic_Video *ev = data;
1251 return ev->video_channels_count;
1255 em_video_channel_set(void *data, int channel)
1257 Emotion_Generic_Video *ev = data;
1259 if (channel < 0 || channel >= ev->video_channels_count)
1261 WRN("video channel out of range.");
1265 _player_send_cmd(ev, EM_CMD_VIDEO_TRACK_SET);
1266 _player_send_int(ev, ev->video_channels[channel].id);
1267 ev->video_channel_current = channel;
1271 em_video_channel_get(void *data)
1273 Emotion_Generic_Video *ev = data;
1274 return ev->video_channel_current;
1278 em_video_channel_name_get(void *data, int channel)
1280 Emotion_Generic_Video *ev = data;
1282 if (channel < 0 || channel >= ev->video_channels_count)
1284 WRN("video channel out of range.");
1288 return ev->video_channels[channel].name;
1292 em_video_channel_mute_set(void *data, int mute)
1294 Emotion_Generic_Video *ev = data;
1296 ev->video_mute = !!mute;
1298 if (!ev || !ev->file_ready)
1301 _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
1302 _player_send_int(ev, mute);
1306 em_video_channel_mute_get(void *data)
1308 Emotion_Generic_Video *ev = data;
1309 return ev->video_mute;
1313 em_audio_channel_count(void *data)
1315 Emotion_Generic_Video *ev = data;
1316 return ev->audio_channels_count;
1320 em_audio_channel_set(void *data, int channel)
1322 Emotion_Generic_Video *ev = data;
1324 if (channel < 0 || channel >= ev->audio_channels_count)
1326 WRN("audio channel out of range.");
1330 _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET);
1331 _player_send_int(ev, ev->audio_channels[channel].id);
1332 ev->audio_channel_current = channel;
1336 em_audio_channel_get(void *data)
1338 Emotion_Generic_Video *ev = data;
1339 return ev->audio_channel_current;
1343 em_audio_channel_name_get(void *data, int channel)
1345 Emotion_Generic_Video *ev = data;
1347 if (channel < 0 || channel >= ev->audio_channels_count)
1349 WRN("audio channel out of range.");
1353 return ev->audio_channels[channel].name;
1357 em_audio_channel_mute_set(void *data, int mute)
1359 Emotion_Generic_Video *ev = data;
1361 ev->audio_mute = !!mute;
1363 if (!ev || !ev->file_ready)
1366 _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
1367 _player_send_int(ev, mute);
1371 em_audio_channel_mute_get(void *data)
1373 Emotion_Generic_Video *ev = data;
1374 return ev->audio_mute;
1378 em_audio_channel_volume_set(void *data, double vol)
1380 Emotion_Generic_Video *ev = data;
1382 if (vol > 1.0) vol = 1.0;
1383 if (vol < 0.0) vol = 0.0;
1387 if (!ev || !ev->file_ready)
1390 _player_send_cmd(ev, EM_CMD_VOLUME_SET);
1391 _player_send_float(ev, ev->volume);
1395 em_audio_channel_volume_get(void *data)
1397 Emotion_Generic_Video *ev = data;
1402 em_spu_channel_count(void *data)
1404 Emotion_Generic_Video *ev = data;
1405 return ev->spu_channels_count;
1409 em_spu_channel_set(void *data, int channel)
1411 Emotion_Generic_Video *ev = data;
1413 if (channel < 0 || channel >= ev->spu_channels_count)
1415 WRN("spu channel out of range.");
1419 _player_send_cmd(ev, EM_CMD_SPU_TRACK_SET);
1420 _player_send_int(ev, ev->spu_channels[channel].id);
1421 ev->spu_channel_current = channel;
1425 em_spu_channel_get(void *data)
1427 Emotion_Generic_Video *ev = data;
1428 return ev->spu_channel_current;
1432 em_spu_channel_name_get(void *data, int channel)
1434 Emotion_Generic_Video *ev = data;
1436 if (channel < 0 || channel >= ev->spu_channels_count)
1438 WRN("spu channel out of range.");
1442 return ev->spu_channels[channel].name;
1446 em_spu_channel_mute_set(void *data, int mute)
1448 Emotion_Generic_Video *ev = data;
1450 ev->spu_mute = !!mute;
1452 if (!ev || !ev->file_ready)
1455 _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
1456 _player_send_int(ev, mute);
1460 em_spu_channel_mute_get(void *data)
1462 Emotion_Generic_Video *ev = data;
1463 return ev->spu_mute;
1467 em_chapter_count(void *ef __UNUSED__)
1474 em_chapter_set(void *ef __UNUSED__, int chapter __UNUSED__)
1479 em_chapter_get(void *ef __UNUSED__)
1486 em_chapter_name_get(void *ef __UNUSED__, int chapter __UNUSED__)
1492 em_speed_set(void *data, double speed)
1494 Emotion_Generic_Video *ev = data;
1498 if (!ev || !ev->file_ready)
1501 _player_send_cmd(ev, EM_CMD_SPEED_SET);
1502 _player_send_float(ev, rate);
1506 em_speed_get(void *data)
1508 Emotion_Generic_Video *ev = data;
1509 return (double)ev->speed;
1513 em_eject(void *ef __UNUSED__)
1519 em_meta_get(void *data, int meta)
1521 Emotion_Generic_Video *ev = data;
1524 case EMOTION_META_INFO_TRACK_TITLE:
1525 return ev->meta.title;
1526 case EMOTION_META_INFO_TRACK_ARTIST:
1527 return ev->meta.artist;
1528 case EMOTION_META_INFO_TRACK_ALBUM:
1529 return ev->meta.album;
1530 case EMOTION_META_INFO_TRACK_YEAR:
1531 return ev->meta.year;
1532 case EMOTION_META_INFO_TRACK_GENRE:
1533 return ev->meta.genre;
1534 case EMOTION_META_INFO_TRACK_COMMENT:
1535 return ev->meta.comment;
1536 case EMOTION_META_INFO_TRACK_DISC_ID:
1537 return ev->meta.disc_id;
1538 case EMOTION_META_INFO_TRACK_COUNT:
1539 return ev->meta.count;
1545 static Emotion_Video_Module em_module =
1548 em_shutdown, /* shutdown */
1549 em_file_open, /* file_open */
1550 em_file_close, /* file_close */
1553 em_size_get, /* size_get */
1554 em_pos_set, /* pos_set */
1555 em_len_get, /* len_get */
1556 em_fps_num_get, /* fps_num_get */
1557 em_fps_den_get, /* fps_den_get */
1558 em_fps_get, /* fps_get */
1559 em_pos_get, /* pos_get */
1560 em_vis_set, /* vis_set */
1561 em_vis_get, /* vis_get */
1562 em_vis_supported, /* vis_supported */
1563 em_ratio_get, /* ratio_get */
1564 em_video_handled, /* video_handled */
1565 em_audio_handled, /* audio_handled */
1566 em_seekable, /* seekable */
1567 em_frame_done, /* frame_done */
1568 em_format_get, /* format_get */
1569 em_video_data_size_get, /* video_data_size_get */
1570 em_yuv_rows_get, /* yuv_rows_get */
1571 em_bgra_data_get, /* bgra_data_get */
1572 em_event_feed, /* event_feed */
1573 em_event_mouse_button_feed, /* event_mouse_button_feed */
1574 em_event_mouse_move_feed, /* event_mouse_move_feed */
1575 em_video_channel_count, /* video_channel_count */
1576 em_video_channel_set, /* video_channel_set */
1577 em_video_channel_get, /* video_channel_get */
1578 em_video_channel_name_get, /* video_channel_name_get */
1579 em_video_channel_mute_set, /* video_channel_mute_set */
1580 em_video_channel_mute_get, /* video_channel_mute_get */
1581 em_audio_channel_count, /* audio_channel_count */
1582 em_audio_channel_set, /* audio_channel_set */
1583 em_audio_channel_get, /* audio_channel_get */
1584 em_audio_channel_name_get, /* audio_channel_name_get */
1585 em_audio_channel_mute_set, /* audio_channel_mute_set */
1586 em_audio_channel_mute_get, /* audio_channel_mute_get */
1587 em_audio_channel_volume_set, /* audio_channel_volume_set */
1588 em_audio_channel_volume_get, /* audio_channel_volume_get */
1589 em_spu_channel_count, /* spu_channel_count */
1590 em_spu_channel_set, /* spu_channel_set */
1591 em_spu_channel_get, /* spu_channel_get */
1592 em_spu_channel_name_get, /* spu_channel_name_get */
1593 em_spu_channel_mute_set, /* spu_channel_mute_set */
1594 em_spu_channel_mute_get, /* spu_channel_mute_get */
1595 em_chapter_count, /* chapter_count */
1596 em_chapter_set, /* chapter_set */
1597 em_chapter_get, /* chapter_get */
1598 em_chapter_name_get, /* chapter_name_get */
1599 em_speed_set, /* speed_set */
1600 em_speed_get, /* speed_get */
1601 em_eject, /* eject */
1602 em_meta_get, /* meta_get */
1607 module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
1613 if (_emotion_generic_log_domain < 0)
1615 eina_threads_init();
1616 eina_log_threads_enable();
1617 _emotion_generic_log_domain = eina_log_domain_register
1618 ("emotion-generic", EINA_COLOR_LIGHTCYAN);
1619 if (_emotion_generic_log_domain < 0)
1621 EINA_LOG_CRIT("Could not register log domain 'emotion-generic'");
1627 if (!em_module.init(obj, video, opt)) {
1631 *module = &em_module;
1636 static void module_close(Emotion_Video_Module *module __UNUSED__, void *video)
1638 em_module.shutdown(video);
1643 generic_module_init(void)
1647 pfx = eina_prefix_new(NULL, emotion_object_add,
1648 "EMOTION", "emotion", NULL,
1653 if (!pfx) return EINA_FALSE;
1655 return _emotion_module_register("generic", module_open, module_close);
1659 generic_module_shutdown(void)
1663 eina_prefix_free(pfx);
1666 _emotion_module_unregister("generic");
1669 #ifndef EMOTION_STATIC_BUILD_GENERIC
1671 EINA_MODULE_INIT(generic_module_init);
1672 EINA_MODULE_SHUTDOWN(generic_module_shutdown);