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 _player_cmd_param_read(Emotion_Generic_Video *ev, void *param, size_t size)
244 ssize_t done, todo, i;
246 /* When a parameter must be read, we cannot make sure it will be entirely
247 * available. Thus we store the bytes that could be read in a temp buffer,
248 * and when more data is read we try to complete the buffer and finally use
253 ev->cmd.tmp = malloc(size);
255 ev->cmd.total = size;
258 todo = ev->cmd.total - ev->cmd.i;
260 done = read(ev->fd_read, &ev->cmd.tmp[i], todo);
262 if (done < 0 && errno != EINTR && errno != EAGAIN)
269 ERR("problem when reading parameter from pipe.");
276 memcpy(param, ev->cmd.tmp, size);
289 _player_frame_resize(Emotion_Generic_Video *ev)
293 w = ev->cmd.param.size.width;
294 h = ev->cmd.param.size.height;
296 INF("received frame resize: %dx%d", w, h);
299 ev->ratio = (float)w / h;
304 _emotion_frame_resize(ev->obj, ev->w, ev->h, ev->ratio);
308 _player_length_changed(Emotion_Generic_Video *ev)
310 float length = ev->cmd.param.f_num;
312 INF("received length changed: %0.3f", length);
315 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
319 _player_position_changed(Emotion_Generic_Video *ev)
321 float position = ev->cmd.param.f_num;
323 INF("received position changed: %0.3f", position);
326 _emotion_video_pos_update(ev->obj, ev->pos, ev->len);
331 float progress = ev->pos / ev->len;
333 snprintf(buf, sizeof(buf), "%0.1f%%", progress * 100);
335 _emotion_progress_set(ev->obj, buf, progress);
339 _player_seekable_changed(Emotion_Generic_Video *ev)
341 int seekable = ev->cmd.param.i_num;
343 INF("received seekable changed: %d", seekable);
345 seekable = !!seekable;
347 ev->seekable = seekable;
351 _audio_channels_free(Emotion_Generic_Video *ev)
354 for (i = 0; i < ev->audio_channels_count; i++)
355 eina_stringshare_del(ev->audio_channels[i].name);
356 free(ev->audio_channels);
357 ev->audio_channels_count = 0;
361 _video_channels_free(Emotion_Generic_Video *ev)
364 for (i = 0; i < ev->video_channels_count; i++)
365 eina_stringshare_del(ev->video_channels[i].name);
366 free(ev->video_channels);
367 ev->video_channels_count = 0;
371 _spu_channels_free(Emotion_Generic_Video *ev)
374 for (i = 0; i < ev->spu_channels_count; i++)
375 eina_stringshare_del(ev->spu_channels[i].name);
376 free(ev->spu_channels);
377 ev->spu_channels_count = 0;
381 _player_tracks_info(Emotion_Generic_Video *ev, Emotion_Generic_Channel **channels, int *count, int *current)
383 Emotion_Generic_Channel *pchannels;
386 *count = ev->cmd.param.track.total;
387 *current = ev->cmd.param.track.current;
388 pchannels = ev->cmd.param.track.channels;
390 INF("number of tracks: %d (current = %d):", *count, *current);
391 for (i = 0; i < *count; i++)
393 INF("\tchannel %d: %s", pchannels[i].id, pchannels[i].name);
396 *channels = pchannels;
400 _player_audio_tracks_info(Emotion_Generic_Video *ev)
402 INF("Receiving audio channels:");
403 if (ev->audio_channels_count)
404 _audio_channels_free(ev);
406 _player_tracks_info(ev, &ev->audio_channels, &ev->audio_channels_count,
407 &ev->audio_channel_current);
411 _player_video_tracks_info(Emotion_Generic_Video *ev)
413 INF("Receiving video channels:");
414 if (ev->video_channels_count)
415 _video_channels_free(ev);
417 _player_tracks_info(ev, &ev->video_channels, &ev->video_channels_count,
418 &ev->video_channel_current);
422 _player_spu_tracks_info(Emotion_Generic_Video *ev)
424 INF("Receiving spu channels:");
425 if (ev->spu_channels_count)
426 _spu_channels_free(ev);
428 _player_tracks_info(ev, &ev->spu_channels, &ev->spu_channels_count,
429 &ev->spu_channel_current);
433 _player_meta_info_free(Emotion_Generic_Video *ev)
435 eina_stringshare_replace(&ev->meta.title, NULL);
436 eina_stringshare_replace(&ev->meta.artist, NULL);
437 eina_stringshare_replace(&ev->meta.album, NULL);
438 eina_stringshare_replace(&ev->meta.year, NULL);
439 eina_stringshare_replace(&ev->meta.genre, NULL);
440 eina_stringshare_replace(&ev->meta.comment, NULL);
441 eina_stringshare_replace(&ev->meta.disc_id, NULL);
442 eina_stringshare_replace(&ev->meta.count, NULL);
446 _player_meta_info_read(Emotion_Generic_Video *ev)
448 INF("Receiving meta info:");
449 _player_meta_info_free(ev);
450 ev->meta.title = ev->cmd.param.meta.title;
451 ev->meta.artist = ev->cmd.param.meta.artist;
452 ev->meta.album = ev->cmd.param.meta.album;
453 ev->meta.year = ev->cmd.param.meta.year;
454 ev->meta.genre = ev->cmd.param.meta.genre;
455 ev->meta.comment = ev->cmd.param.meta.comment;
456 ev->meta.disc_id = ev->cmd.param.meta.disc_id;
457 ev->meta.count = ev->cmd.param.meta.count;
458 INF("title: '%s'", ev->meta.title);
459 INF("artist: '%s'", ev->meta.artist);
460 INF("album: '%s'", ev->meta.album);
461 INF("year: '%s'", ev->meta.year);
462 INF("genre: '%s'", ev->meta.genre);
463 INF("comment: '%s'", ev->meta.comment);
464 INF("disc_id: '%s'", ev->meta.disc_id);
465 INF("count: '%s'", ev->meta.count);
469 _player_file_closed(Emotion_Generic_Video *ev)
471 INF("Closed previous file.");
472 sem_destroy(&ev->shared->lock);
474 ev->closing = EINA_FALSE;
481 _player_open_done(Emotion_Generic_Video *ev)
485 success = ev->cmd.param.i_num;
486 shm_unlink(ev->shmname);
488 if (ev->file_changed)
491 ev->file_changed = EINA_FALSE;
495 ev->opening = EINA_FALSE;
498 ERR("Could not open file.");
502 ev->file_ready = EINA_TRUE;
504 _emotion_open_done(ev->obj);
508 _player_send_cmd(ev, EM_CMD_PLAY);
509 _player_send_float(ev, ev->pos);
512 _player_send_cmd(ev, EM_CMD_VOLUME_SET);
513 _player_send_float(ev, ev->volume);
515 _player_send_cmd(ev, EM_CMD_SPEED_SET);
516 _player_send_float(ev, ev->speed);
518 int mute = ev->audio_mute;
519 _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
520 _player_send_int(ev, mute);
522 mute = ev->video_mute;
523 _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
524 _player_send_int(ev, mute);
527 _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
528 _player_send_int(ev, mute);
534 _player_cmd_process(Emotion_Generic_Video *ev)
536 switch (ev->cmd.type) {
540 case EM_RESULT_FRAME_NEW:
541 _player_new_frame(ev);
543 case EM_RESULT_FILE_SET:
544 _player_file_set_done(ev);
546 case EM_RESULT_FILE_SET_DONE:
547 _player_open_done(ev);
549 case EM_RESULT_FILE_CLOSE:
550 _player_file_closed(ev);
552 case EM_RESULT_PLAYBACK_STOPPED:
553 _emotion_playback_finished(ev->obj);
555 case EM_RESULT_FRAME_SIZE:
556 _player_frame_resize(ev);
558 case EM_RESULT_LENGTH_CHANGED:
559 _player_length_changed(ev);
561 case EM_RESULT_POSITION_CHANGED:
562 _player_position_changed(ev);
564 case EM_RESULT_SEEKABLE_CHANGED:
565 _player_seekable_changed(ev);
567 case EM_RESULT_AUDIO_TRACK_INFO:
568 _player_audio_tracks_info(ev);
570 case EM_RESULT_VIDEO_TRACK_INFO:
571 _player_video_tracks_info(ev);
573 case EM_RESULT_SPU_TRACK_INFO:
574 _player_spu_tracks_info(ev);
576 case EM_RESULT_META_INFO:
577 _player_meta_info_read(ev);
580 WRN("received wrong command: %d", ev->cmd.type);
587 _player_cmd_single_int_process(Emotion_Generic_Video *ev)
589 if (!_player_cmd_param_read(ev, &ev->cmd.param.i_num, sizeof(ev->cmd.param.i_num)))
592 _player_cmd_process(ev);
596 _player_cmd_single_float_process(Emotion_Generic_Video *ev)
598 if (!_player_cmd_param_read(ev, &ev->cmd.param.f_num, sizeof(ev->cmd.param.f_num)))
601 _player_cmd_process(ev);
605 _player_cmd_double_int_process(Emotion_Generic_Video *ev)
609 if (ev->cmd.num_params == 0)
611 ev->cmd.num_params = 2;
612 ev->cmd.cur_param = 0;
613 ev->cmd.param.size.width = 0;
614 ev->cmd.param.size.height = 0;
617 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
620 if (ev->cmd.cur_param == 0)
621 ev->cmd.param.size.width = param;
623 ev->cmd.param.size.height = param;
626 if (ev->cmd.cur_param == ev->cmd.num_params)
627 _player_cmd_process(ev);
631 _player_cmd_track_info(Emotion_Generic_Video *ev)
636 if (ev->cmd.num_params == 0)
638 ev->cmd.cur_param = 0;
639 ev->cmd.num_params = 2;
640 ev->cmd.param.track.channels = NULL;
644 while (ev->cmd.cur_param < 2)
646 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
649 if (ev->cmd.cur_param == 0)
650 ev->cmd.param.track.current = param;
653 ev->cmd.param.track.total = param;
654 ev->cmd.num_params += param * 2;
655 ev->cmd.param.track.channels =
656 calloc(param, sizeof(*ev->cmd.param.track.channels));
661 if (ev->cmd.cur_param == ev->cmd.num_params)
663 _player_cmd_process(ev);
667 i = (ev->cmd.cur_param - 2) / 2;
668 if ((ev->cmd.cur_param % 2) == 0) // reading track id
670 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
672 ev->cmd.param.track.channels[i].id = param;
675 else // reading track name
679 if (ev->cmd.s_len == -1)
681 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
683 ev->cmd.s_len = param;
686 if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len))
688 ev->cmd.param.track.channels[i].name =
689 eina_stringshare_add_length(buf, ev->cmd.s_len);
694 if (ev->cmd.cur_param == ev->cmd.num_params)
695 _player_cmd_process(ev);
699 _player_cmd_meta_info(Emotion_Generic_Video *ev)
705 if (ev->cmd.num_params == 0)
707 ev->cmd.cur_param = 0;
708 ev->cmd.num_params = 8;
709 ev->cmd.param.meta.title = NULL;
710 ev->cmd.param.meta.artist = NULL;
711 ev->cmd.param.meta.album = NULL;
712 ev->cmd.param.meta.year = NULL;
713 ev->cmd.param.meta.genre = NULL;
714 ev->cmd.param.meta.comment = NULL;
715 ev->cmd.param.meta.disc_id = NULL;
716 ev->cmd.param.meta.count = NULL;
720 if (ev->cmd.s_len == -1)
722 if (!_player_cmd_param_read(ev, ¶m, sizeof(param)))
724 ev->cmd.s_len = param;
727 if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len))
730 info = eina_stringshare_add_length(buf, ev->cmd.s_len);
733 if (ev->cmd.cur_param == 0)
734 ev->cmd.param.meta.title = info;
735 else if (ev->cmd.cur_param == 1)
736 ev->cmd.param.meta.artist = info;
737 else if (ev->cmd.cur_param == 2)
738 ev->cmd.param.meta.album = info;
739 else if (ev->cmd.cur_param == 3)
740 ev->cmd.param.meta.year = info;
741 else if (ev->cmd.cur_param == 4)
742 ev->cmd.param.meta.genre = info;
743 else if (ev->cmd.cur_param == 5)
744 ev->cmd.param.meta.comment = info;
745 else if (ev->cmd.cur_param == 6)
746 ev->cmd.param.meta.disc_id = info;
747 else if (ev->cmd.cur_param == 7)
748 ev->cmd.param.meta.count = info;
752 if (ev->cmd.cur_param == 8)
753 _player_cmd_process(ev);
757 _player_cmd_read(Emotion_Generic_Video *ev)
759 if (ev->cmd.type < 0)
761 if (!_player_cmd_param_read(ev, &ev->cmd.type, sizeof(ev->cmd.type)))
763 ev->cmd.num_params = 0;
766 switch (ev->cmd.type) {
768 case EM_RESULT_FILE_SET:
769 case EM_RESULT_PLAYBACK_STOPPED:
770 case EM_RESULT_FILE_CLOSE:
771 case EM_RESULT_FRAME_NEW:
772 _player_cmd_process(ev);
774 case EM_RESULT_FILE_SET_DONE:
775 case EM_RESULT_SEEKABLE_CHANGED:
776 _player_cmd_single_int_process(ev);
778 case EM_RESULT_LENGTH_CHANGED:
779 case EM_RESULT_POSITION_CHANGED:
780 _player_cmd_single_float_process(ev);
782 case EM_RESULT_FRAME_SIZE:
783 _player_cmd_double_int_process(ev);
785 case EM_RESULT_AUDIO_TRACK_INFO:
786 case EM_RESULT_VIDEO_TRACK_INFO:
787 case EM_RESULT_SPU_TRACK_INFO:
788 _player_cmd_track_info(ev);
790 case EM_RESULT_META_INFO:
791 _player_cmd_meta_info(ev);
795 WRN("received wrong command: %d", ev->cmd.type);
801 _player_cmd_handler_cb(void *data, Ecore_Fd_Handler *fd_handler)
803 Emotion_Generic_Video *ev = data;
805 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
807 ERR("an error occurred on fd_read %d.", ev->fd_read);
808 return ECORE_CALLBACK_CANCEL;
811 _player_cmd_read(ev);
813 return ECORE_CALLBACK_RENEW;
817 _player_data_cb(void *data, int type __UNUSED__, void *event)
819 Ecore_Exe_Event_Data *ev = event;
820 Emotion_Generic_Video *evideo = data;
823 if (ev->exe != evideo->player.exe)
825 ERR("slave != ev->exe");
826 return ECORE_CALLBACK_DONE;
829 for (i = 0; ev->lines[i].line; i++)
830 INF("received input from player: \"%s\"", ev->lines[i].line);
832 return ECORE_CALLBACK_DONE;
836 _player_add_cb(void *data, int type __UNUSED__, void *event)
838 Ecore_Exe_Event_Add *event_add = event;
839 Ecore_Exe *player = event_add->exe;
840 Emotion_Generic_Video *ev = data;
842 if (ev->player.exe != player)
844 ERR("ev->player != player.");
845 return ECORE_CALLBACK_DONE;
848 _player_send_cmd(ev, EM_CMD_INIT);
849 _player_send_str(ev, ev->shmname, EINA_TRUE);
851 return ECORE_CALLBACK_DONE;
855 _player_del_cb(void *data, int type __UNUSED__, void *event __UNUSED__)
857 Emotion_Generic_Video *ev = data;
860 ev->player.exe = NULL;
861 ev->ready = EINA_FALSE;
862 ev->file_ready = EINA_FALSE;
863 ecore_main_fd_handler_del(ev->fd_handler);
868 _emotion_decode_stop(ev->obj);
870 return ECORE_CALLBACK_DONE;
874 _player_exec(Emotion_Generic_Video *ev)
880 if (pipe(pipe_out) == -1)
882 ERR("could not create pipe for communication emotion -> player: %s", strerror(errno));
886 if (pipe(pipe_in) == -1)
888 ERR("could not create pipe for communication player -> emotion: %s", strerror(errno));
894 snprintf(buf, sizeof(buf), "%s %d %d\n", ev->cmdline, pipe_out[0], pipe_in[1]);
896 ev->player.exe = ecore_exe_pipe_run(
898 ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE |
899 ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER,
902 INF("created pipe emotion -> player: %d -> %d\n", pipe_out[1], pipe_out[0]);
903 INF("created pipe player -> emotion: %d -> %d\n", pipe_in[1], pipe_in[0]);
915 ev->fd_read = pipe_in[0];
916 ev->fd_write = pipe_out[1];
918 ev->fd_handler = ecore_main_fd_handler_add(
919 ev->fd_read, ECORE_FD_READ | ECORE_FD_ERROR, _player_cmd_handler_cb, ev,
926 _fork_and_exec(Evas_Object *obj __UNUSED__, Emotion_Generic_Video *ev)
931 gettimeofday(&tv, NULL);
932 snprintf(shmname, sizeof(shmname), "/em-generic-shm_%d_%d",
933 (int)tv.tv_sec, (int)tv.tv_usec);
935 ev->shmname = eina_stringshare_add(shmname);
937 ev->player_add = ecore_event_handler_add(
938 ECORE_EXE_EVENT_ADD, _player_add_cb, ev);
939 ev->player_del = ecore_event_handler_add(
940 ECORE_EXE_EVENT_DEL, _player_del_cb, ev);
941 ev->player_data = ecore_event_handler_add(
942 ECORE_EXE_EVENT_DATA, _player_data_cb, ev);
945 if (!_player_exec(ev))
947 ERR("could not start player.");
951 ev->initializing = EINA_TRUE;
957 em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
959 Emotion_Generic_Video *ev;
962 if (!emotion_video) return 0;
963 player = _get_player(opt ? opt->player : NULL);
964 if (!player) return 0;
966 ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev));
973 ev->audio_mute = EINA_FALSE;
977 ev->cmdline = eina_stringshare_add(player);
980 return _fork_and_exec(obj, ev);
984 em_shutdown(void *data)
986 Emotion_Generic_Video *ev = data;
992 ecore_exe_terminate(ev->player.exe);
993 ecore_exe_free(ev->player.exe);
994 ev->player.exe = NULL;
998 munmap(ev->shared, ev->shared->size);
1000 if (ev->fd_read >= 0)
1002 if (ev->fd_write >= 0)
1003 close(ev->fd_write);
1005 ecore_main_fd_handler_del(ev->fd_handler);
1007 eina_stringshare_del(ev->cmdline);
1008 eina_stringshare_del(ev->shmname);
1010 ecore_event_handler_del(ev->player_add);
1011 ecore_event_handler_del(ev->player_data);
1012 ecore_event_handler_del(ev->player_del);
1017 static unsigned char
1018 em_file_open(const char *file, Evas_Object *obj __UNUSED__, void *data)
1020 Emotion_Generic_Video *ev = data;
1021 INF("file set: %s", file);
1024 eina_stringshare_replace(&ev->filename, file);
1032 if (ev->ready && ev->opening)
1034 INF("file changed while opening.");
1035 ev->file_changed = EINA_TRUE;
1039 ev->opening = EINA_TRUE;
1048 em_file_close(void *data)
1050 Emotion_Generic_Video *ev = data;
1052 if (!ev || !ev->filename) return;
1054 INF("file close: %s", ev->filename);
1056 eina_stringshare_replace(&ev->filename, NULL);
1058 ev->file_ready = EINA_FALSE;
1059 _audio_channels_free(ev);
1060 _video_channels_free(ev);
1061 _spu_channels_free(ev);
1062 _player_meta_info_free(ev);
1067 _player_send_cmd(ev, EM_CMD_FILE_CLOSE);
1068 ev->closing = EINA_TRUE;
1071 static Emotion_Format
1072 em_format_get(void *ef __UNUSED__)
1074 return EMOTION_FORMAT_BGRA;
1078 em_video_data_size_get(void *data, int *w, int *h)
1080 Emotion_Generic_Video *ev = data;
1088 em_play(void *data, double pos)
1090 Emotion_Generic_Video *ev = data;
1095 ev->play = EINA_TRUE;
1096 INF("play: %0.3f", pos);
1098 if (ev->initializing || ev->opening)
1103 _player_send_cmd(ev, EM_CMD_PLAY);
1104 _player_send_float(ev, ev->pos);
1108 if (!_player_exec(ev))
1109 ERR("could not start player.");
1115 Emotion_Generic_Video *ev = data;
1120 ev->play = EINA_FALSE;
1122 if (!ev->file_ready)
1125 _player_send_cmd(ev, EM_CMD_STOP);
1126 _emotion_decode_stop(ev->obj);
1130 em_size_get(void *data, int *w, int *h)
1132 Emotion_Generic_Video *ev = data;
1138 em_pos_set(void *data, double pos)
1140 Emotion_Generic_Video *ev = data;
1141 float position = pos;
1143 if (!ev->file_ready)
1146 _player_send_cmd(ev, EM_CMD_POSITION_SET);
1147 _player_send_float(ev, position);
1148 _emotion_seek_done(ev->obj);
1152 em_len_get(void *data)
1154 Emotion_Generic_Video *ev = data;
1159 em_fps_num_get(void *data)
1161 Emotion_Generic_Video *ev = data;
1162 return (int)(ev->fps * 1000.0);
1166 em_fps_den_get(void *ef __UNUSED__)
1172 em_fps_get(void *data)
1174 Emotion_Generic_Video *ev = data;
1179 em_pos_get(void *data)
1181 Emotion_Generic_Video *ev = data;
1186 em_vis_set(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
1191 em_vis_get(void *data)
1193 Emotion_Generic_Video *ev = data;
1198 em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__)
1204 em_ratio_get(void *data)
1206 Emotion_Generic_Video *ev = data;
1210 static int em_video_handled(void *ef __UNUSED__)
1212 fprintf(stderr, "video handled!\n");
1216 static int em_audio_handled(void *ef __UNUSED__)
1218 fprintf(stderr, "audio handled!\n");
1222 static int em_seekable(void *data)
1224 Emotion_Generic_Video *ev = data;
1225 return ev->seekable;
1228 static void em_frame_done(void *ef __UNUSED__)
1233 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__)
1239 em_bgra_data_get(void *data, unsigned char **bgra_data)
1241 Emotion_Generic_Video *ev = data;
1243 if (!ev || !ev->file_ready)
1247 sem_wait(&ev->shared->lock);
1249 // send current frame to emotion
1250 if (ev->shared->frame.emotion != ev->shared->frame.last)
1252 ev->shared->frame.next = ev->shared->frame.emotion;
1253 ev->shared->frame.emotion = ev->shared->frame.last;
1255 *bgra_data = ev->frame.frames[ev->shared->frame.emotion];
1257 if (ev->shared->frame_drop > 1)
1258 WRN("dropped frames: %d", ev->shared->frame_drop - 1);
1259 ev->shared->frame_drop = 0;
1261 // unlock frame here
1262 sem_post(&ev->shared->lock);
1269 em_event_feed(void *ef __UNUSED__, int event __UNUSED__)
1274 em_event_mouse_button_feed(void *ef __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1279 em_event_mouse_move_feed(void *ef __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1284 em_video_channel_count(void *data)
1286 Emotion_Generic_Video *ev = data;
1287 return ev->video_channels_count;
1291 em_video_channel_set(void *data, int channel)
1293 Emotion_Generic_Video *ev = data;
1295 if (channel < 0 || channel >= ev->video_channels_count)
1297 WRN("video channel out of range.");
1301 _player_send_cmd(ev, EM_CMD_VIDEO_TRACK_SET);
1302 _player_send_int(ev, ev->video_channels[channel].id);
1303 ev->video_channel_current = channel;
1307 em_video_channel_get(void *data)
1309 Emotion_Generic_Video *ev = data;
1310 return ev->video_channel_current;
1314 em_video_channel_name_get(void *data, int channel)
1316 Emotion_Generic_Video *ev = data;
1318 if (channel < 0 || channel >= ev->video_channels_count)
1320 WRN("video channel out of range.");
1324 return ev->video_channels[channel].name;
1328 em_video_channel_mute_set(void *data, int mute)
1330 Emotion_Generic_Video *ev = data;
1332 ev->video_mute = !!mute;
1334 if (!ev || !ev->file_ready)
1337 _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET);
1338 _player_send_int(ev, mute);
1342 em_video_channel_mute_get(void *data)
1344 Emotion_Generic_Video *ev = data;
1345 return ev->video_mute;
1349 em_audio_channel_count(void *data)
1351 Emotion_Generic_Video *ev = data;
1352 return ev->audio_channels_count;
1356 em_audio_channel_set(void *data, int channel)
1358 Emotion_Generic_Video *ev = data;
1360 if (channel < 0 || channel >= ev->audio_channels_count)
1362 WRN("audio channel out of range.");
1366 _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET);
1367 _player_send_int(ev, ev->audio_channels[channel].id);
1368 ev->audio_channel_current = channel;
1372 em_audio_channel_get(void *data)
1374 Emotion_Generic_Video *ev = data;
1375 return ev->audio_channel_current;
1379 em_audio_channel_name_get(void *data, int channel)
1381 Emotion_Generic_Video *ev = data;
1383 if (channel < 0 || channel >= ev->audio_channels_count)
1385 WRN("audio channel out of range.");
1389 return ev->audio_channels[channel].name;
1393 em_audio_channel_mute_set(void *data, int mute)
1395 Emotion_Generic_Video *ev = data;
1397 ev->audio_mute = !!mute;
1399 if (!ev || !ev->file_ready)
1402 _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET);
1403 _player_send_int(ev, mute);
1407 em_audio_channel_mute_get(void *data)
1409 Emotion_Generic_Video *ev = data;
1410 return ev->audio_mute;
1414 em_audio_channel_volume_set(void *data, double vol)
1416 Emotion_Generic_Video *ev = data;
1418 if (vol > 1.0) vol = 1.0;
1419 if (vol < 0.0) vol = 0.0;
1423 if (!ev || !ev->file_ready)
1426 _player_send_cmd(ev, EM_CMD_VOLUME_SET);
1427 _player_send_float(ev, ev->volume);
1431 em_audio_channel_volume_get(void *data)
1433 Emotion_Generic_Video *ev = data;
1438 em_spu_channel_count(void *data)
1440 Emotion_Generic_Video *ev = data;
1441 return ev->spu_channels_count;
1445 em_spu_channel_set(void *data, int channel)
1447 Emotion_Generic_Video *ev = data;
1449 if (channel < 0 || channel >= ev->spu_channels_count)
1451 WRN("spu channel out of range.");
1455 _player_send_cmd(ev, EM_CMD_SPU_TRACK_SET);
1456 _player_send_int(ev, ev->spu_channels[channel].id);
1457 ev->spu_channel_current = channel;
1461 em_spu_channel_get(void *data)
1463 Emotion_Generic_Video *ev = data;
1464 return ev->spu_channel_current;
1468 em_spu_channel_name_get(void *data, int channel)
1470 Emotion_Generic_Video *ev = data;
1472 if (channel < 0 || channel >= ev->spu_channels_count)
1474 WRN("spu channel out of range.");
1478 return ev->spu_channels[channel].name;
1482 em_spu_channel_mute_set(void *data, int mute)
1484 Emotion_Generic_Video *ev = data;
1486 ev->spu_mute = !!mute;
1488 if (!ev || !ev->file_ready)
1491 _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET);
1492 _player_send_int(ev, mute);
1496 em_spu_channel_mute_get(void *data)
1498 Emotion_Generic_Video *ev = data;
1499 return ev->spu_mute;
1503 em_chapter_count(void *ef __UNUSED__)
1510 em_chapter_set(void *ef __UNUSED__, int chapter __UNUSED__)
1515 em_chapter_get(void *ef __UNUSED__)
1522 em_chapter_name_get(void *ef __UNUSED__, int chapter __UNUSED__)
1528 em_speed_set(void *data, double speed)
1530 Emotion_Generic_Video *ev = data;
1534 if (!ev || !ev->file_ready)
1537 _player_send_cmd(ev, EM_CMD_SPEED_SET);
1538 _player_send_float(ev, rate);
1542 em_speed_get(void *data)
1544 Emotion_Generic_Video *ev = data;
1545 return (double)ev->speed;
1549 em_eject(void *ef __UNUSED__)
1555 em_meta_get(void *data, int meta)
1557 Emotion_Generic_Video *ev = data;
1560 case EMOTION_META_INFO_TRACK_TITLE:
1561 return ev->meta.title;
1562 case EMOTION_META_INFO_TRACK_ARTIST:
1563 return ev->meta.artist;
1564 case EMOTION_META_INFO_TRACK_ALBUM:
1565 return ev->meta.album;
1566 case EMOTION_META_INFO_TRACK_YEAR:
1567 return ev->meta.year;
1568 case EMOTION_META_INFO_TRACK_GENRE:
1569 return ev->meta.genre;
1570 case EMOTION_META_INFO_TRACK_COMMENT:
1571 return ev->meta.comment;
1572 case EMOTION_META_INFO_TRACK_DISC_ID:
1573 return ev->meta.disc_id;
1574 case EMOTION_META_INFO_TRACK_COUNT:
1575 return ev->meta.count;
1581 static Emotion_Video_Module em_module =
1584 em_shutdown, /* shutdown */
1585 em_file_open, /* file_open */
1586 em_file_close, /* file_close */
1589 em_size_get, /* size_get */
1590 em_pos_set, /* pos_set */
1591 em_len_get, /* len_get */
1592 em_fps_num_get, /* fps_num_get */
1593 em_fps_den_get, /* fps_den_get */
1594 em_fps_get, /* fps_get */
1595 em_pos_get, /* pos_get */
1596 em_vis_set, /* vis_set */
1597 em_vis_get, /* vis_get */
1598 em_vis_supported, /* vis_supported */
1599 em_ratio_get, /* ratio_get */
1600 em_video_handled, /* video_handled */
1601 em_audio_handled, /* audio_handled */
1602 em_seekable, /* seekable */
1603 em_frame_done, /* frame_done */
1604 em_format_get, /* format_get */
1605 em_video_data_size_get, /* video_data_size_get */
1606 em_yuv_rows_get, /* yuv_rows_get */
1607 em_bgra_data_get, /* bgra_data_get */
1608 em_event_feed, /* event_feed */
1609 em_event_mouse_button_feed, /* event_mouse_button_feed */
1610 em_event_mouse_move_feed, /* event_mouse_move_feed */
1611 em_video_channel_count, /* video_channel_count */
1612 em_video_channel_set, /* video_channel_set */
1613 em_video_channel_get, /* video_channel_get */
1614 em_video_channel_name_get, /* video_channel_name_get */
1615 em_video_channel_mute_set, /* video_channel_mute_set */
1616 em_video_channel_mute_get, /* video_channel_mute_get */
1617 em_audio_channel_count, /* audio_channel_count */
1618 em_audio_channel_set, /* audio_channel_set */
1619 em_audio_channel_get, /* audio_channel_get */
1620 em_audio_channel_name_get, /* audio_channel_name_get */
1621 em_audio_channel_mute_set, /* audio_channel_mute_set */
1622 em_audio_channel_mute_get, /* audio_channel_mute_get */
1623 em_audio_channel_volume_set, /* audio_channel_volume_set */
1624 em_audio_channel_volume_get, /* audio_channel_volume_get */
1625 em_spu_channel_count, /* spu_channel_count */
1626 em_spu_channel_set, /* spu_channel_set */
1627 em_spu_channel_get, /* spu_channel_get */
1628 em_spu_channel_name_get, /* spu_channel_name_get */
1629 em_spu_channel_mute_set, /* spu_channel_mute_set */
1630 em_spu_channel_mute_get, /* spu_channel_mute_get */
1631 em_chapter_count, /* chapter_count */
1632 em_chapter_set, /* chapter_set */
1633 em_chapter_get, /* chapter_get */
1634 em_chapter_name_get, /* chapter_name_get */
1635 em_speed_set, /* speed_set */
1636 em_speed_get, /* speed_get */
1637 em_eject, /* eject */
1638 em_meta_get, /* meta_get */
1639 NULL, /* priority_set */
1640 NULL, /* priority_get */
1645 module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
1651 if (_emotion_generic_log_domain < 0)
1653 eina_threads_init();
1654 eina_log_threads_enable();
1655 _emotion_generic_log_domain = eina_log_domain_register
1656 ("emotion-generic", EINA_COLOR_LIGHTCYAN);
1657 if (_emotion_generic_log_domain < 0)
1659 EINA_LOG_CRIT("Could not register log domain 'emotion-generic'");
1665 if (!em_module.init(obj, video, opt)) {
1669 *module = &em_module;
1674 static void module_close(Emotion_Video_Module *module __UNUSED__, void *video)
1676 em_module.shutdown(video);
1681 generic_module_init(void)
1685 pfx = eina_prefix_new(NULL, emotion_object_add,
1686 "EMOTION", "emotion", NULL,
1691 if (!pfx) return EINA_FALSE;
1693 return _emotion_module_register("generic", module_open, module_close);
1697 generic_module_shutdown(void)
1701 eina_prefix_free(pfx);
1704 _emotion_module_unregister("generic");
1707 #ifndef EMOTION_STATIC_BUILD_GENERIC
1709 EINA_MODULE_INIT(generic_module_init);
1710 EINA_MODULE_SHUTDOWN(generic_module_shutdown);