forked from enlightenment/rage
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1214 lines
32 KiB
1214 lines
32 KiB
#include <Elementary.h> |
|
#include "video.h" |
|
#include "rage_config.h" |
|
#include "config.h" |
|
#include "albumart.h" |
|
#include "mpris.h" |
|
|
|
typedef struct _Video Video; |
|
|
|
struct _Video |
|
{ |
|
Evas_Object_Smart_Clipped_Data __clipped_data; |
|
Evas_Object *clip, *o_vid, *o_img, *o_event; |
|
Ecore_Timer *smooth_timer; |
|
Ecore_Job *restart_job; |
|
const char *file; |
|
const char *realfile; |
|
const char *artfile; |
|
Ecore_Exe *exe; |
|
Ecore_Event_Handler *exe_handler; |
|
double volume; |
|
int w, h; |
|
int iw, ih, piw, pih, tw, th; |
|
int resizes; |
|
struct { |
|
Evas_Coord x, y; |
|
Eina_Bool down : 1; |
|
} down; |
|
Eina_Bool nosmooth : 1; |
|
Eina_Bool lowqual : 1; |
|
Eina_Bool loop : 1; |
|
Eina_Bool fill : 1; |
|
Eina_Bool novid : 1; |
|
Eina_Bool doart : 1; |
|
}; |
|
|
|
static Evas_Smart *_smart = NULL; |
|
static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL; |
|
|
|
static void _ob_resize(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); |
|
|
|
static Eina_Bool |
|
_cb_thumb_exe(void *data, int type EINA_UNUSED, void *event) |
|
{ |
|
Ecore_Exe_Event_Del *ev = event; |
|
Video *sd = evas_object_smart_data_get(data); |
|
char *path; |
|
|
|
if (!sd) return EINA_TRUE; |
|
if (ev->exe == sd->exe) |
|
{ |
|
sd->exe = NULL; |
|
if (ev->exit_code == 0) |
|
{ |
|
Evas_Coord ox, oy, ow, oh; |
|
|
|
path = albumart_file_get(sd->realfile); |
|
if (path) |
|
{ |
|
if (ecore_file_exists(path)) |
|
{ |
|
eina_stringshare_replace(&(sd->artfile), path); |
|
evas_object_image_file_set(sd->o_img, path, NULL); |
|
evas_object_image_size_get(sd->o_img, &(sd->tw), &(sd->th)); |
|
evas_object_geometry_get(data, &ox, &oy, &ow, &oh); |
|
evas_object_show(sd->o_img); |
|
_ob_resize(data, ox, oy, ow, oh); |
|
mpris_metadata_change(); |
|
} |
|
free(path); |
|
} |
|
} |
|
} |
|
return EINA_TRUE; |
|
} |
|
|
|
static void |
|
_art_check(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
if (!sd->novid) |
|
{ |
|
if (!emotion_object_video_handled_get(sd->o_vid)) |
|
sd->novid = EINA_TRUE; |
|
} |
|
else |
|
{ |
|
if (!emotion_object_video_handled_get(sd->o_vid)) |
|
sd->novid = EINA_FALSE; |
|
} |
|
if (sd->doart) |
|
{ |
|
char *thumb = NULL; |
|
|
|
thumb = albumart_file_get(sd->realfile); |
|
if (thumb) |
|
{ |
|
Evas_Coord ox, oy, ow, oh; |
|
|
|
if (ecore_file_exists(thumb)) |
|
{ |
|
evas_object_image_file_set(sd->o_img, thumb, NULL); |
|
evas_object_image_size_get(sd->o_img, &(sd->tw), &(sd->th)); |
|
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); |
|
_ob_resize(obj, ox, oy, ow, oh); |
|
if (sd->tw > 0) |
|
{ |
|
eina_stringshare_replace(&(sd->artfile), thumb); |
|
mpris_metadata_change(); |
|
} |
|
} |
|
free(thumb); |
|
} |
|
} |
|
else |
|
{ |
|
evas_object_hide(sd->o_img); |
|
} |
|
|
|
if (!sd->artfile) |
|
{ |
|
char buf[PATH_MAX]; |
|
const char *libdir; |
|
char *s; |
|
|
|
ecore_exe_run_priority_set(10); |
|
s = ecore_file_escape_name(sd->realfile); |
|
if (s) |
|
{ |
|
libdir = elm_app_lib_dir_get(); |
|
if (libdir) |
|
{ |
|
if (!sd->exe_handler) |
|
sd->exe_handler = ecore_event_handler_add |
|
(ECORE_EXE_EVENT_DEL, _cb_thumb_exe, obj); |
|
snprintf(buf, sizeof(buf), |
|
"%s/rage/utils/rage_thumb %s 10000 %i", |
|
libdir, s, 2); |
|
if (sd->exe) |
|
{ |
|
ecore_exe_kill(sd->exe); |
|
ecore_exe_free(sd->exe); |
|
sd->exe = NULL; |
|
} |
|
sd->exe = ecore_exe_pipe_run(buf, |
|
ECORE_EXE_TERM_WITH_PARENT | |
|
ECORE_EXE_NOT_LEADER, |
|
obj); |
|
} |
|
free(s); |
|
} |
|
} |
|
} |
|
|
|
static void |
|
_cb_vid_frame(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
Evas_Coord ox, oy, ow, oh; |
|
|
|
if (!sd) return; |
|
evas_object_geometry_get(data, &ox, &oy, &ow, &oh); |
|
if (!emotion_object_video_handled_get(sd->o_vid)) |
|
{ |
|
evas_object_hide(sd->o_vid); |
|
evas_object_show(sd->o_img); |
|
} |
|
else |
|
{ |
|
evas_object_show(sd->o_vid); |
|
evas_object_hide(sd->o_img); |
|
} |
|
evas_object_show(sd->clip); |
|
_ob_resize(data, ox, oy, ow, oh); |
|
evas_object_smart_callback_call(data, "frame_decode", NULL); |
|
} |
|
|
|
static void |
|
_cb_vid_resize(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
Evas_Coord ox, oy, ow, oh; |
|
|
|
if (!sd) return; |
|
evas_object_geometry_get(data, &ox, &oy, &ow, &oh); |
|
_ob_resize(data, ox, oy, ow, oh); |
|
} |
|
|
|
static void |
|
_cb_restart(void *data) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
sd->restart_job = NULL; |
|
emotion_object_position_set(sd->o_vid, 0.0); |
|
emotion_object_play_set(sd->o_vid, EINA_TRUE); |
|
} |
|
|
|
static void |
|
_cb_vid_stop(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
if (sd->restart_job) ecore_job_del(sd->restart_job); |
|
if (sd->loop) |
|
{ |
|
sd->restart_job = ecore_job_add(_cb_restart, data); |
|
evas_object_smart_callback_call(data, "loop", NULL); |
|
mpris_metadata_change(); |
|
} |
|
else |
|
{ |
|
sd->restart_job = NULL; |
|
evas_object_smart_callback_call(data, "stop", NULL); |
|
mpris_metadata_change(); |
|
} |
|
} |
|
|
|
static void |
|
_cb_vid_progress(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "frame_decode", NULL); |
|
} |
|
|
|
static void |
|
_cb_vid_ref(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "frame_decode", NULL); |
|
} |
|
|
|
static void |
|
_cb_open_done(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "opened", NULL); |
|
_art_check(data); |
|
mpris_metadata_change(); |
|
} |
|
|
|
static void |
|
_cb_position_update(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "frame_decode", NULL); |
|
} |
|
|
|
static void |
|
_cb_length_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "length", NULL); |
|
mpris_metadata_change(); |
|
} |
|
|
|
static void |
|
_cb_title_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "title", NULL); |
|
mpris_metadata_change(); |
|
} |
|
|
|
static void |
|
_cb_audio_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "audio", NULL); |
|
mpris_metadata_change(); |
|
} |
|
|
|
static void |
|
_cb_channels_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "channels", NULL); |
|
mpris_metadata_change(); |
|
} |
|
|
|
static void |
|
_cb_play_start(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "play_start", NULL); |
|
evas_object_smart_callback_call(data, "audio", NULL); |
|
mpris_metadata_change(); |
|
} |
|
|
|
static void |
|
_cb_play_finish(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "play_finish", NULL); |
|
evas_object_smart_callback_call(data, "audio", NULL); |
|
mpris_metadata_change(); |
|
} |
|
|
|
static void |
|
_cb_button_num_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "button_num", NULL); |
|
} |
|
|
|
static void |
|
_cb_button_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
evas_object_smart_callback_call(data, "button", NULL); |
|
} |
|
|
|
static void |
|
_ob_resize(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
|
|
emotion_object_size_get(sd->o_vid, &(sd->iw), &(sd->ih)); |
|
if (!sd->fill) |
|
{ |
|
if ((w <= 0) || (h <= 0) || (sd->iw <= 0) || (sd->ih <= 0)) |
|
{ |
|
w = 1; |
|
h = 1; |
|
} |
|
else |
|
{ |
|
int iw = 1, ih = 1; |
|
double ratio; |
|
|
|
ratio = emotion_object_ratio_get(sd->o_vid); |
|
if (ratio > 0.0) sd->iw = (sd->ih * ratio); |
|
else ratio = (double)sd->iw / (double)sd->ih; |
|
|
|
iw = w; |
|
ih = ((double)w + 1.0) / ratio; |
|
if (ih > h) |
|
{ |
|
ih = h; |
|
iw = h * ratio; |
|
if (iw > w) iw = w; |
|
} |
|
x += ((w - iw) / 2); |
|
y += ((h - ih) / 2); |
|
w = iw; |
|
h = ih; |
|
} |
|
} |
|
evas_object_move(sd->o_vid, x, y); |
|
evas_object_resize(sd->o_vid, w, h); |
|
if ((sd->piw != sd->iw) || (sd->pih != sd->ih)) |
|
{ |
|
sd->piw = sd->iw; |
|
sd->pih = sd->ih; |
|
evas_object_smart_callback_call(obj, "frame_resize", NULL); |
|
} |
|
if ((sd->tw > 0) && (sd->th > 0) && (sd->doart) && |
|
(!emotion_object_video_handled_get(sd->o_vid))) |
|
{ |
|
int iw, ih; |
|
|
|
iw = (sd->tw * h) / sd->th; |
|
ih = h; |
|
if (iw < w) |
|
{ |
|
ih = (sd->th * w) / sd->tw; |
|
iw = w; |
|
} |
|
x += ((w - iw) / 2); |
|
y += ((h - ih) / 2); |
|
w = iw; |
|
h = ih; |
|
evas_object_show(sd->o_img); |
|
} |
|
else |
|
{ |
|
evas_object_hide(sd->o_img); |
|
} |
|
evas_object_move(sd->o_img, x, y); |
|
evas_object_resize(sd->o_img, w, h); |
|
} |
|
|
|
static void _smart_calculate(Evas_Object *obj); |
|
|
|
static void |
|
_smart_add(Evas_Object *obj) |
|
{ |
|
Video *sd; |
|
Evas_Object *o; |
|
|
|
sd = calloc(1, sizeof(Video)); |
|
EINA_SAFETY_ON_NULL_RETURN(sd); |
|
evas_object_smart_data_set(obj, sd); |
|
|
|
_parent_sc.add(obj); |
|
|
|
o = evas_object_rectangle_add(evas_object_evas_get(obj)); |
|
evas_object_color_set(o, 255, 255, 255, 255); |
|
evas_object_smart_member_add(o, obj); |
|
sd->clip = o; |
|
} |
|
|
|
static void |
|
_smart_del(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
if (sd->file) eina_stringshare_del(sd->file); |
|
if (sd->realfile) eina_stringshare_del(sd->realfile); |
|
if (sd->artfile) eina_stringshare_del(sd->artfile); |
|
if (sd->clip) evas_object_del(sd->clip); |
|
if (sd->o_vid) evas_object_del(sd->o_vid); |
|
if (sd->o_img) evas_object_del(sd->o_img); |
|
if (sd->o_event) evas_object_del(sd->o_event); |
|
if (sd->smooth_timer) sd->smooth_timer = ecore_timer_del(sd->smooth_timer); |
|
if (sd->restart_job) ecore_job_del(sd->restart_job); |
|
|
|
if (sd->exe) |
|
{ |
|
ecore_exe_kill(sd->exe); |
|
ecore_exe_free(sd->exe); |
|
sd->exe = NULL; |
|
} |
|
if (sd->exe_handler) |
|
{ |
|
ecore_event_handler_del(sd->exe_handler); |
|
sd->exe_handler = NULL; |
|
} |
|
_parent_sc.del(obj); |
|
free(sd); |
|
|
|
emotion_shutdown(); |
|
} |
|
|
|
static void |
|
_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
Evas_Coord ow, oh; |
|
if (!sd) return; |
|
evas_object_geometry_get(obj, NULL, NULL, &ow, &oh); |
|
if ((ow == w) && (oh == h)) return; |
|
evas_object_smart_changed(obj); |
|
} |
|
|
|
static Eina_Bool |
|
_unsmooth_timeout(void *data) |
|
{ |
|
Video *sd = evas_object_smart_data_get(data); |
|
Evas_Coord ox, oy, ow, oh; |
|
|
|
if (!sd) return EINA_FALSE; |
|
evas_object_geometry_get(data, &ox, &oy, &ow, &oh); |
|
sd->smooth_timer = NULL; |
|
sd->nosmooth = EINA_FALSE; |
|
emotion_object_smooth_scale_set(sd->o_vid, |
|
(!sd->nosmooth) & (!sd->lowqual)); |
|
return EINA_FALSE; |
|
} |
|
|
|
static void |
|
_smooth_handler(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
double interval; |
|
|
|
if (!sd) return; |
|
interval = ecore_animator_frametime_get(); |
|
if (interval <= 0.0) interval = 1.0/60.0; |
|
if (!sd->nosmooth) |
|
{ |
|
if (sd->resizes >= 2) |
|
{ |
|
sd->nosmooth = EINA_TRUE; |
|
sd->resizes = 0; |
|
emotion_object_smooth_scale_set(sd->o_vid, |
|
(!sd->nosmooth) & (!sd->lowqual)); |
|
if (sd->smooth_timer) |
|
sd->smooth_timer = ecore_timer_del(sd->smooth_timer); |
|
sd->smooth_timer = ecore_timer_add(interval * 10, |
|
_unsmooth_timeout, obj); |
|
} |
|
} |
|
else |
|
{ |
|
if (sd->smooth_timer) |
|
sd->smooth_timer = ecore_timer_del(sd->smooth_timer); |
|
sd->smooth_timer = ecore_timer_add(interval * 10, |
|
_unsmooth_timeout, obj); |
|
} |
|
} |
|
|
|
static void |
|
_smart_calculate(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
Evas_Coord ox, oy, ow, oh; |
|
|
|
if (!sd) return; |
|
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); |
|
if ((ow != sd->w) || (oh != sd->h)) sd->resizes++; |
|
else sd->resizes = 0; |
|
_smooth_handler(obj); |
|
sd->w = ow; |
|
sd->h = oh; |
|
_ob_resize(obj, ox, oy, ow, oh); |
|
evas_object_move(sd->clip, ox, oy); |
|
evas_object_resize(sd->clip, ow, oh); |
|
} |
|
|
|
static void |
|
_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) |
|
{ |
|
Evas_Event_Mouse_Down *ev = event; |
|
Video *sd = evas_object_smart_data_get(data); |
|
if (!sd) return; |
|
|
|
if (sd->down.down) return; |
|
if (ev->button != 1) return; |
|
sd->down.x = ev->canvas.x; |
|
sd->down.y = ev->canvas.y; |
|
sd->down.down = EINA_TRUE; |
|
} |
|
|
|
static void |
|
_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) |
|
{ |
|
Evas_Event_Mouse_Down *ev = event; |
|
Video *sd = evas_object_smart_data_get(data); |
|
Evas_Coord dx, dy; |
|
if (!sd) return; |
|
|
|
if (!sd->down.down) return; |
|
sd->down.down = EINA_FALSE; |
|
dx = abs(ev->canvas.x - sd->down.x); |
|
dy = abs(ev->canvas.y - sd->down.y); |
|
if ((dx <= elm_config_finger_size_get()) && |
|
(dy <= elm_config_finger_size_get())) |
|
evas_object_smart_callback_call(data, "clicked", NULL); |
|
} |
|
|
|
static void |
|
_smart_init(void) |
|
{ |
|
static Evas_Smart_Class sc; |
|
|
|
evas_object_smart_clipped_smart_set(&_parent_sc); |
|
sc = _parent_sc; |
|
sc.name = "video"; |
|
sc.version = EVAS_SMART_CLASS_VERSION; |
|
sc.add = _smart_add; |
|
sc.del = _smart_del; |
|
sc.resize = _smart_resize; |
|
sc.calculate = _smart_calculate; |
|
_smart = evas_smart_class_new(&sc); |
|
} |
|
|
|
Evas_Object * |
|
video_add(Evas_Object *parent) |
|
{ |
|
Evas *e; |
|
Evas_Object *obj, *o; |
|
Video *sd; |
|
// XXX: to do later |
|
// Config *config; |
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); |
|
e = evas_object_evas_get(parent); |
|
if (!e) return NULL; |
|
|
|
if (!_smart) _smart_init(); |
|
obj = evas_object_smart_add(e, _smart); |
|
sd = evas_object_smart_data_get(obj); |
|
if (!sd) return obj; |
|
|
|
emotion_init(); |
|
o = sd->o_vid = emotion_object_add(evas_object_evas_get(obj)); |
|
emotion_object_keep_aspect_set(o, EMOTION_ASPECT_KEEP_NONE); |
|
// XXX: to do later |
|
// config = config_get(); |
|
evas_object_smart_callback_add(o, "frame_decode", _cb_vid_frame, obj); |
|
evas_object_smart_callback_add(o, "frame_resize", _cb_vid_resize, obj); |
|
evas_object_smart_callback_add(o, "decode_stop", _cb_vid_stop, obj); |
|
evas_object_smart_callback_add(o, "progress_change", _cb_vid_progress, obj); |
|
evas_object_smart_callback_add(o, "ref_change", _cb_vid_ref, obj); |
|
evas_object_smart_callback_add(o, "open_done", _cb_open_done, obj); |
|
evas_object_smart_callback_add(o, "position_update", _cb_position_update, obj); |
|
evas_object_smart_callback_add(o, "length_change", _cb_length_change, obj); |
|
evas_object_smart_callback_add(o, "title_change", _cb_title_change, obj); |
|
evas_object_smart_callback_add(o, "audio_level_change", _cb_audio_change, obj); |
|
evas_object_smart_callback_add(o, "channels_change", _cb_channels_change, obj); |
|
evas_object_smart_callback_add(o, "playback_started", _cb_play_start, obj); |
|
evas_object_smart_callback_add(o, "playback_finished", _cb_play_finish, obj); |
|
evas_object_smart_callback_add(o, "button_num_change", _cb_button_num_change, obj); |
|
evas_object_smart_callback_add(o, "button_change", _cb_button_change, obj); |
|
evas_object_smart_member_add(o, obj); |
|
evas_object_clip_set(o, sd->clip); |
|
|
|
sd->o_img = evas_object_image_filled_add(e); |
|
evas_object_smart_member_add(sd->o_img, obj); |
|
|
|
sd->o_event = evas_object_rectangle_add(e); |
|
evas_object_color_set(sd->o_event, 0, 0, 0, 0); |
|
evas_object_repeat_events_set(sd->o_event, EINA_TRUE); |
|
evas_object_smart_member_add(sd->o_event, obj); |
|
evas_object_clip_set(sd->o_event, sd->clip); |
|
evas_object_show(sd->o_event); |
|
evas_object_event_callback_add(sd->o_event, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, obj); |
|
evas_object_event_callback_add(sd->o_event, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, obj); |
|
return obj; |
|
} |
|
|
|
void |
|
video_file_set(Evas_Object *obj, const char *file) |
|
{ |
|
char *realfile = NULL; |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
evas_object_hide(sd->o_img); |
|
evas_object_hide(sd->o_vid); |
|
evas_object_hide(sd->clip); |
|
eina_stringshare_replace(&(sd->file), file); |
|
if (sd->file) |
|
{ |
|
const char *colon = strchr(sd->file, ':'); |
|
Eina_Bool is_url = EINA_FALSE; |
|
|
|
if ((colon) && (colon[1] == '/') && (colon[2] == '/')) |
|
is_url = EINA_TRUE; |
|
if (!strncasecmp(sd->file, "file:/", 6)) |
|
{ |
|
Efreet_Uri *uri = efreet_uri_decode(sd->file); |
|
if (uri) |
|
{ |
|
realfile = ecore_file_realpath(uri->path); |
|
efreet_uri_free(uri); |
|
} |
|
} |
|
else if (is_url) |
|
realfile = strdup(sd->file); |
|
else |
|
realfile = ecore_file_realpath(sd->file); |
|
eina_stringshare_replace(&(sd->realfile), realfile); |
|
free(realfile); |
|
eina_stringshare_replace(&(sd->artfile), NULL); |
|
emotion_object_file_set(sd->o_vid, sd->file); |
|
video_position_set(obj, 0.0); |
|
if (sd->doart) |
|
{ |
|
const char *extn = strchr(sd->file, '.'); |
|
if (extn) |
|
{ |
|
if ((!strcasecmp(extn, ".mp3")) || |
|
(!strcasecmp(extn, ".m4a")) || |
|
(!strcasecmp(extn, ".oga")) || |
|
(!strcasecmp(extn, ".aac")) || |
|
(!strcasecmp(extn, ".flac")) || |
|
(!strcasecmp(extn, ".wav"))) |
|
{ |
|
_art_check(obj); |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
eina_stringshare_replace(&(sd->realfile), NULL); |
|
eina_stringshare_replace(&(sd->artfile), NULL); |
|
} |
|
} |
|
|
|
const char * |
|
video_file_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return sd->file; |
|
} |
|
|
|
void |
|
video_sub_file_set(Evas_Object *obj, const char *file) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
if ((!file) || (file && (!file[0]))) |
|
emotion_object_spu_mute_set(sd->o_vid, EINA_TRUE); |
|
else |
|
emotion_object_spu_mute_set(sd->o_vid, EINA_FALSE); |
|
emotion_object_video_subtitle_file_set(sd->o_vid, file); |
|
} |
|
|
|
void |
|
video_mute_set(Evas_Object *obj, Eina_Bool mute) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
emotion_object_audio_mute_set(sd->o_vid, mute); |
|
evas_object_smart_callback_call(obj, "audio", NULL); |
|
} |
|
|
|
Eina_Bool |
|
video_mute_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return EINA_FALSE; |
|
return emotion_object_audio_mute_get(sd->o_vid); |
|
} |
|
|
|
void |
|
video_play_set(Evas_Object *obj, Eina_Bool play) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
|
|
if (sd->volume) |
|
video_volume_set(obj, sd->volume); |
|
|
|
emotion_object_play_set(sd->o_vid, play); |
|
} |
|
|
|
Eina_Bool |
|
video_play_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return EINA_FALSE; |
|
return emotion_object_play_get(sd->o_vid); |
|
} |
|
|
|
void |
|
video_loop_set(Evas_Object *obj, Eina_Bool loop) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
sd->loop = loop; |
|
} |
|
|
|
Eina_Bool |
|
video_loop_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return EINA_FALSE; |
|
return sd->loop; |
|
} |
|
|
|
void |
|
video_art_set(Evas_Object *obj, Eina_Bool art) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
sd->doart = art; |
|
if (!sd->doart) evas_object_hide(sd->o_img); |
|
} |
|
|
|
Eina_Bool |
|
video_art_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return EINA_FALSE; |
|
return sd->doart; |
|
} |
|
|
|
void |
|
video_fill_set(Evas_Object *obj, Eina_Bool fill) |
|
{ |
|
Evas_Coord ox, oy, ow, oh; |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
sd->fill = fill; |
|
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); |
|
_ob_resize(obj, ox, oy, ow, oh); |
|
} |
|
|
|
Eina_Bool |
|
video_fill_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return EINA_FALSE; |
|
return sd->fill; |
|
} |
|
|
|
void |
|
video_stop(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
evas_object_hide(sd->o_vid); |
|
evas_object_hide(sd->clip); |
|
emotion_object_play_set(sd->o_vid, EINA_FALSE); |
|
emotion_object_position_set(sd->o_vid, 0.0); |
|
} |
|
|
|
void |
|
video_position_set(Evas_Object *obj, double pos) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
emotion_object_position_set(sd->o_vid, pos); |
|
} |
|
|
|
double |
|
video_position_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0.0; |
|
return emotion_object_position_get(sd->o_vid); |
|
} |
|
|
|
double |
|
video_length_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0.0; |
|
return emotion_object_play_length_get(sd->o_vid); |
|
} |
|
|
|
void |
|
video_ratio_size_get(Evas_Object *obj, int *w, int *h) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
*w = 1; |
|
*h = 1; |
|
if (!sd) return; |
|
emotion_object_size_get(sd->o_vid, &(sd->iw), &(sd->ih)); |
|
if ((sd->iw <= 0) || (sd->ih <= 0)) |
|
{ |
|
*w = 1; |
|
*h = 1; |
|
} |
|
else |
|
{ |
|
double ratio; |
|
|
|
ratio = emotion_object_ratio_get(sd->o_vid); |
|
if (ratio > 0.0) sd->iw = (sd->ih * ratio) + 0.5; |
|
else ratio = (double)sd->iw / (double)sd->ih; |
|
*w = sd->iw; |
|
*h = sd->ih; |
|
} |
|
} |
|
|
|
void |
|
video_eject(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
emotion_object_eject(sd->o_vid); |
|
} |
|
|
|
int |
|
video_chapter_count(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_chapter_count(sd->o_vid); |
|
} |
|
|
|
void |
|
video_chapter_set(Evas_Object *obj, int chapter) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
emotion_object_chapter_set(sd->o_vid, chapter); |
|
} |
|
|
|
int |
|
video_chapter_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_chapter_get(sd->o_vid); |
|
} |
|
|
|
const char * |
|
video_chapter_name_get(Evas_Object *obj, int chapter) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_chapter_name_get(sd->o_vid, chapter); |
|
} |
|
|
|
void |
|
video_volume_set(Evas_Object *obj, double vol) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
emotion_object_audio_volume_set(sd->o_vid, vol); |
|
sd->volume = vol; |
|
evas_object_smart_callback_call(obj, "audio", NULL); |
|
} |
|
|
|
double |
|
video_volume_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0.0; |
|
return emotion_object_audio_volume_get(sd->o_vid); |
|
} |
|
|
|
Eina_Bool |
|
video_has_video_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return EINA_FALSE; |
|
return emotion_object_video_handled_get(sd->o_vid); |
|
} |
|
|
|
Eina_Bool |
|
video_has_audio_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return EINA_FALSE; |
|
return emotion_object_audio_handled_get(sd->o_vid); |
|
} |
|
|
|
const char * |
|
video_title_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_title_get(sd->o_vid); |
|
} |
|
|
|
int |
|
video_audio_channel_count(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_audio_channel_count(sd->o_vid); |
|
} |
|
|
|
void |
|
video_audio_channel_set(Evas_Object *obj, int chan) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
emotion_object_audio_channel_set(sd->o_vid, chan); |
|
} |
|
|
|
int |
|
video_audio_channel_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_audio_channel_get(sd->o_vid); |
|
} |
|
|
|
const char * |
|
video_audio_channel_name_get(Evas_Object *obj, int chan) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_audio_channel_name_get(sd->o_vid, chan); |
|
} |
|
|
|
int |
|
video_video_channel_count(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_video_channel_count(sd->o_vid); |
|
} |
|
|
|
void |
|
video_video_channel_set(Evas_Object *obj, int chan) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
emotion_object_video_channel_set(sd->o_vid, chan); |
|
} |
|
|
|
int |
|
video_video_channel_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_video_channel_get(sd->o_vid); |
|
} |
|
|
|
const char * |
|
video_video_channel_name_get(Evas_Object *obj, int chan) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_video_channel_name_get(sd->o_vid, chan); |
|
} |
|
|
|
int |
|
video_spu_channel_count(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_spu_channel_count(sd->o_vid); |
|
} |
|
|
|
void |
|
video_spu_channel_set(Evas_Object *obj, int chan) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
emotion_object_spu_channel_set(sd->o_vid, chan); |
|
} |
|
|
|
int |
|
video_spu_channel_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_spu_channel_get(sd->o_vid); |
|
} |
|
|
|
const char * |
|
video_spu_channel_name_get(Evas_Object *obj, int chan) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_spu_channel_name_get(sd->o_vid, chan); |
|
} |
|
|
|
int |
|
video_spu_button_count(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_spu_button_count_get(sd->o_vid); |
|
} |
|
|
|
int |
|
video_spu_button_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return 0; |
|
return emotion_object_spu_button_get(sd->o_vid); |
|
} |
|
|
|
void |
|
video_event_send(Evas_Object *obj, Emotion_Event ev) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
emotion_object_event_simple_send(sd->o_vid, ev); |
|
} |
|
|
|
void |
|
video_lowquality_set(Evas_Object *obj, Eina_Bool lowq) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return; |
|
sd->lowqual = lowq; |
|
emotion_object_smooth_scale_set(sd->o_vid, |
|
(!sd->nosmooth) & (!sd->lowqual)); |
|
} |
|
|
|
Eina_Bool |
|
video_lowquality_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return EINA_FALSE; |
|
return sd->lowqual; |
|
} |
|
|
|
const char * |
|
video_meta_title_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_meta_info_get(sd->o_vid, EMOTION_META_INFO_TRACK_TITLE); |
|
} |
|
|
|
const char * |
|
video_meta_artist_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_meta_info_get(sd->o_vid, EMOTION_META_INFO_TRACK_ARTIST); |
|
} |
|
|
|
const char * |
|
video_meta_album_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_meta_info_get(sd->o_vid, EMOTION_META_INFO_TRACK_ALBUM); |
|
} |
|
|
|
const char * |
|
video_meta_year_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_meta_info_get(sd->o_vid, EMOTION_META_INFO_TRACK_YEAR); |
|
} |
|
|
|
Evas_Object * |
|
video_meta_artwork_get(Evas_Object *obj, const char *path, int type) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_file_meta_artwork_get(sd->o_vid, path, type); |
|
} |
|
|
|
const char * |
|
video_meta_genre_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_meta_info_get(sd->o_vid, EMOTION_META_INFO_TRACK_GENRE); |
|
} |
|
|
|
const char * |
|
video_meta_comment_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return emotion_object_meta_info_get(sd->o_vid, EMOTION_META_INFO_TRACK_COMMENT); |
|
} |
|
|
|
void |
|
video_file_autosub_set(Evas_Object *obj, const char *file, const char *sub) |
|
{ |
|
if ((file) && (!sub)) |
|
{ |
|
const char *subtypes[] = |
|
{ |
|
".srt", |
|
".SRT", |
|
".sub", |
|
".SUB", |
|
NULL |
|
}; |
|
char *sub = alloca(strlen(file) + 1 + 16); |
|
char *p; |
|
int i; |
|
Eina_Bool found = EINA_FALSE; |
|
|
|
// try last dont in filename first... |
|
strcpy(sub, file); |
|
p = strrchr(sub, '.'); |
|
if (p) |
|
{ |
|
for (i = 0; subtypes[i]; i++) |
|
{ |
|
strcpy(p, subtypes[i]); |
|
if (ecore_file_exists(sub)) |
|
{ |
|
video_sub_file_set(obj, sub); |
|
found = EINA_TRUE; |
|
break; |
|
} |
|
} |
|
} |
|
// now try first dot as a fallback. |
|
if (!found) |
|
{ |
|
strcpy(sub, file); |
|
p = strchr(sub, '.'); |
|
if (p) |
|
{ |
|
for (i = 0; subtypes[i]; i++) |
|
{ |
|
strcpy(p, subtypes[i]); |
|
if (ecore_file_exists(sub)) |
|
{ |
|
video_sub_file_set(obj, sub); |
|
found = EINA_TRUE; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
if (!found) video_sub_file_set(obj, NULL); |
|
} |
|
else |
|
{ |
|
video_sub_file_set(obj, sub); |
|
} |
|
|
|
if (file) |
|
video_file_set(obj, file); |
|
} |
|
|
|
const char * |
|
video_artfile_get(Evas_Object *obj) |
|
{ |
|
Video *sd = evas_object_smart_data_get(obj); |
|
if (!sd) return NULL; |
|
return sd->artfile; |
|
} |
|
|
|
// emotion_object_seekable_get |
|
// emotion_object_play_speed_set |
|
// emotion_object_play_speed_get |
|
// emotion_object_meta_info_get |
|
// emotion_object_buffer_size_get |
|
// emotion_object_video_mute_set |
|
// emotion_object_video_mute_get |
|
// emotion_object_spu_mute_set |
|
// emotion_object_spu_mute_get |
|
// emotion_object_progress_info_get |
|
// emotion_object_progress_status_get |
|
// emotion_object_ref_file_get
|
|
|