Browse Source

rage - initial import of working code

v-0.4.0
Carsten Haitzler 9 years ago
commit
86a4a3704a
  1. 4
      .arcconfig
  2. 48
      .gitignore
  3. 1
      AUTHORS
  4. 25
      COPYING
  5. 0
      ChangeLog
  6. 11
      INSTALL
  7. 34
      Makefile.am
  8. 0
      NEWS
  9. 24
      README
  10. 19
      TODO
  11. 16
      autogen.sh
  12. 80
      configure.ac
  13. 3
      data/Makefile.am
  14. 6
      data/desktop/Makefile.am
  15. 11
      data/desktop/rage.desktop
  16. 6
      data/icons/Makefile.am
  17. BIN
      data/icons/rage.png
  18. 28
      data/themes/Makefile.am
  19. 1075
      data/themes/default.edc
  20. 29
      data/themes/images/Makefile.am
  21. BIN
      data/themes/images/glow_exclam.png
  22. BIN
      data/themes/images/horizontal_separated_bar_small_glow.png
  23. BIN
      data/themes/images/icon_arrow_right.png
  24. BIN
      data/themes/images/icon_eject.png
  25. BIN
      data/themes/images/icon_forward.png
  26. BIN
      data/themes/images/icon_mute.png
  27. BIN
      data/themes/images/icon_next.png
  28. BIN
      data/themes/images/icon_next2.png
  29. BIN
      data/themes/images/icon_pause.png
  30. BIN
      data/themes/images/icon_pause2.png
  31. BIN
      data/themes/images/icon_play.png
  32. BIN
      data/themes/images/icon_play2.png
  33. BIN
      data/themes/images/icon_prev.png
  34. BIN
      data/themes/images/icon_prev2.png
  35. BIN
      data/themes/images/icon_refresh.png
  36. BIN
      data/themes/images/icon_rewind.png
  37. BIN
      data/themes/images/icon_spanner.png
  38. BIN
      data/themes/images/icon_spanner2.png
  39. BIN
      data/themes/images/icon_stop.png
  40. BIN
      data/themes/images/icon_volume.png
  41. BIN
      data/themes/images/icon_volume2.png
  42. BIN
      data/themes/images/pm_fill.png
  43. BIN
      data/themes/images/pm_overlay.png
  44. BIN
      data/themes/images/pm_shadow.png
  45. BIN
      data/themes/images/pos_indicator.png
  46. BIN
      data/themes/images/pos_indicator_big.png
  47. BIN
      data/themes/images/vgrad_shadow_bi.png
  48. 47
      m4/ac_attribute.m4
  49. 5
      m4/efl_beta.m4
  50. 71
      m4/efl_binary.m4
  51. 6
      m4/efl_eo.m4
  52. 33
      pkgbuild/PKGBUILD.in
  53. 48
      rage.spec.in
  54. 2
      src/Makefile.am
  55. 14
      src/bin/Makefile.am
  56. 1013
      src/bin/main.c
  57. 6
      src/bin/main.h
  58. 828
      src/bin/video.c
  59. 47
      src/bin/video.h

4
.arcconfig

@ -0,0 +1,4 @@
{
"project_id" : "rage",
"conduit_uri" : "https://phab.enlightenment.org/"
}

48
.gitignore vendored

@ -0,0 +1,48 @@
*~
*.o
*.swo
*.swp
/Makefile
/Makefile.in
/aclocal.m4
/compile
/config.log
/config.status
/configure
/depcomp
/install-sh
/ltmain.sh
/missing
/stamp-h1
/rage_config.h
/rage_config.h.in
/rage.spec
/autom4te.cache/
/data/Makefile
/data/Makefile.in
/data/desktop/Makefile
/data/desktop/Makefile.in
/data/icons/Makefile
/data/icons/Makefile.in
/data/images/Makefile
/data/images/Makefile.in
/data/themes/Makefile
/data/themes/Makefile.in
/data/themes/default.edj
/data/themes/images/Makefile
/data/themes/images/Makefile.in
/m4/libtool.m4
/m4/ltoptions.m4
/m4/ltsugar.m4
/m4/ltversion.m4
/m4/lt~obsolete.m4
/src/Makefile
/src/Makefile.in
/src/bin/.deps/
/src/bin/Makefile
/src/bin/Makefile.in
/src/bin/rage
pkgbuild/PKGBUILD
pkgbuild/pkg
pkgbuild/src
pkgbuild/*.tar.xz

1
AUTHORS

@ -0,0 +1 @@
Carsten Haitzler <raster@rasterman.com>

25
COPYING

@ -0,0 +1,25 @@
Copyright notice for Terminology:
Copyright (C) 2014 Carsten Haitzler and various contributors (see AUTHORS)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

11
INSTALL

@ -0,0 +1,11 @@
COMPILING and INSTALLING:
If you got a official release tar archive do:
./configure
Then to compile:
make
To install (run this as root, or the user who handles installs):
make install

34
Makefile.am

@ -0,0 +1,34 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src data
MAINTAINERCLEANFILES = \
Makefile.in \
$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz \
$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.bz2 \
aclocal.m4 \
config.guess \
rage_config.h.in \
config.sub \
configure \
compile \
depcomp \
install-sh \
ltconfig \
ltmain.sh \
missing \
mkinstalldirs \
stamp-h.in \
stamp-h \
m4/libtool.m4 \
m4/lt~obsolete.m4 \
m4/ltoptions.m4 \
m4/ltsugar.m4 \
m4/ltversion.m4
EXTRA_DIST = README AUTHORS COPYING autogen.sh rage.spec pkgbuild/PKGBUILD
.PHONY: doc
doc:
@echo "Empty doc target until we have real documentation."

24
README

@ -0,0 +1,24 @@
Rage 0.1.0
******************************************************************************
FOR ANY ISSUES PLEASE EMAIL:
enlightenment-devel@lists.sourceforge.net
******************************************************************************
Requirements:
-------------
* elementary (>= 1.9.0)
* eina (>= 1.9.0)
* eet (>= 1.9.0)
* evas (>= 1.9.0)
* ecore (>= 1.9.0)
* edje (>= 1.9.0)
* emotion (>= 1.9.0)
* ecore-imf (>= 1.9.0)
* ecore-imf-evas (>= 1.9.0)
* ecore-input (>= 1.9.0)
* ethumb (>= 1.9.0)

19
TODO

@ -0,0 +1,19 @@
* volume status display when changed (slider/image/percentage)
* elm gesture drag to left/right for forward/rewind
* elm gesture drag up/down for prev/next
* emotion engine selection options
* timeline thumbnails on position slider
* playlist display + selection from playlist (on left?)
* right click control panel (ala terminology)
* about display/popup (from panel?)
* mouse wheel for forward/rewind and/or prev/next and/or volume up/down
* audio channel list/selection
* spu channel list/selection
* video channel list/selection
* handle non-seekable content (eg streams)
* prefer gl engine (needs wl/x11 independent preference selection)
* cmdline options
* add subtitle file cmdline
* loop all option
* show busy anim until opened cb or failure
* quality option (smooth)

16
autogen.sh

@ -0,0 +1,16 @@
#!/bin/sh
rm -rf autom4te.cache
rm -f aclocal.m4 ltmain.sh
touch README
echo "Running aclocal..." ; aclocal -I m4 $ACLOCAL_FLAGS || exit 1
echo "Running autoheader..." ; autoheader || exit 1
echo "Running autoconf..." ; autoconf || exit 1
echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
if [ -z "$NOCONFIGURE" ]; then
./configure "$@"
fi

80
configure.ac

@ -0,0 +1,80 @@
dnl Process this file with autoconf to produce a configure script.
# get rid of that stupid cache mechanism
rm -f config.cache
AC_INIT([rage], [0.1.0], [enlightenment-devel@lists.sourceforge.net])
AC_PREREQ([2.60])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([rage_config.h])
AM_INIT_AUTOMAKE([1.6 dist-bzip2])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AM_PROG_CC_C_O
AC_C___ATTRIBUTE__
efl_version="1.8.99"
AC_SUBST(efl_version)
requirements="\
elementary >= ${efl_version} \
eina >= ${efl_version} \
eet >= ${efl_version} \
evas >= ${efl_version} \
ecore >= ${efl_version} \
ecore-evas >= ${efl_version} \
ecore-file >= ${efl_version} \
edje >= ${efl_version} \
emotion >= ${efl_version} \
ecore-input >= ${efl_version} \
ecore-imf >= ${efl_version} \
ecore-imf-evas >= ${efl_version} \
ecore-ipc >= ${efl_version} \
efreet >= ${efl_version} \
ethumb_client >= ${efl_version} \
"
EFL_ENABLE_EO_API_SUPPORT
EFL_ENABLE_BETA_API_SUPPORT
PKG_CHECK_MODULES([RAGE], [${requirements}])
EFL_WITH_BIN([edje], [edje-cc], [edje_cc])
AC_CONFIG_FILES([
Makefile
rage.spec
src/Makefile
src/bin/Makefile
data/Makefile
data/desktop/Makefile
data/icons/Makefile
data/themes/Makefile
data/themes/images/Makefile
pkgbuild/PKGBUILD
])
AC_OUTPUT
#####################################################################
## Info
echo
echo
echo
echo "------------------------------------------------------------------------"
echo "$PACKAGE $VERSION"
echo "------------------------------------------------------------------------"
echo
echo "Compilation................: make (or gmake)"
echo " CPPFLAGS.................: $CPPFLAGS"
echo " CFLAGS...................: $CFLAGS"
echo " LDFLAGS..................: $LDFLAGS"
echo
echo "Installation...............: make install (as root if needed, with 'su' or 'sudo')"
echo " prefix...................: $prefix"

3
data/Makefile.am

@ -0,0 +1,3 @@
MAINTAINERCLEANFILES = Makefile.in
SUBDIRS = desktop icons themes

6
data/desktop/Makefile.am

@ -0,0 +1,6 @@
MAINTAINERCLEANFILES = Makefile.in
filesdir = $(datadir)/applications
files_DATA = \
rage.desktop
EXTRA_DIST = $(files_DATA)

11
data/desktop/rage.desktop

@ -0,0 +1,11 @@
[Desktop Entry]
#Encoding=UTF-8
Type=Application
Name=Rage
GenericName=Video Player
Comment=Video player
Exec=rage
Icon=rage
Categories=AudioVideo;Player;
StartupWMClass=rage
MimeType=application/mxf;application/ogg;application/ram;application/sdp;application/smil;application/smil+xml;application/vnd.ms-wpl;application/vnd.rn-realmedia;application/x-extension-m4a;application/x-extension-mp4;application/x-flac;application/x-flash-video;application/x-matroska;application/x-netshow-channel;application/x-ogg;application/x-quicktime-media-link;application/x-quicktimeplayer;application/x-shorten;application/x-smil;application/xspf+xml;audio/3gpp;audio/ac3;audio/AMR;audio/AMR-WB;audio/basic;audio/midi;audio/mp4;audio/mpeg;audio/mpegurl;audio/ogg;audio/prs.sid;audio/vnd.rn-realaudio;audio/x-aiff;audio/x-ape;audio/x-flac;audio/x-gsm;audio/x-it;audio/x-m4a;audio/x-matroska;audio/x-mod;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-asf;audio/x-ms-asx;audio/x-ms-wax;audio/x-ms-wma;audio/x-musepack;audio/x-pn-aiff;audio/x-pn-au;audio/x-pn-realaudio;audio/x-pn-realaudio-plugin;audio/x-pn-wav;audio/x-pn-windows-acm;audio/x-realaudio;audio/x-real-audio;audio/x-sbc;audio/x-scpls;audio/x-speex;audio/x-tta;audio/x-wav;audio/x-wavpack;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-xm;image/vnd.rn-realpix;image/x-pict;misc/ultravox;text/google-video-pointer;text/x-google-video-pointer;video/3gpp;video/dv;video/fli;video/flv;video/mp2t;video/mp4;video/mp4v-es;video/mpeg;video/msvideo;video/ogg;video/quicktime;video/vivo;video/vnd.divx;video/vnd.rn-realvideo;video/vnd.vivo;video/webm;video/x-anim;video/x-avi;video/x-flc;video/x-fli;video/x-flic;video/x-flv;video/x-m4v;video/x-matroska;video/x-mpeg;video/x-ms-asf;video/x-ms-asx;video/x-msvideo;video/x-ms-wm;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvx;video/x-nsv;video/x-ogm+ogg;video/x-theora+ogg;video/x-totem-stream;x-content/video-dvd;x-content/video-vcd;x-content/video-svcd;

6
data/icons/Makefile.am

@ -0,0 +1,6 @@
MAINTAINERCLEANFILES = Makefile.in
filesdir = $(datadir)/icons
files_DATA = \
rage.png
EXTRA_DIST = $(files_DATA)

BIN
data/icons/rage.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

28
data/themes/Makefile.am

@ -0,0 +1,28 @@
MAINTAINERCLEANFILES = Makefile.in
SUBDIRS = images
EDJE_CC = @edje_cc@
EDJE_FLAGS_VERBOSE_ =
EDJE_FLAGS_VERBOSE_0 =
EDJE_FLAGS_VERBOSE_1 = -v
EDJE_FLAGS = $(EDJE_FLAGS_VERBOSE_$(V)) -id $(top_srcdir)/data/themes/images
filesdir = $(pkgdatadir)/themes
files_DATA = \
default.edj
AM_V_EDJ = $(am__v_EDJ_$(V))
am__v_EDJ_ = $(am__v_EDJ_$(AM_DEFAULT_VERBOSITY))
am__v_EDJ_0 = @echo " EDJ " $@;
EXTRA_DIST = \
default.edc
default.edj: Makefile default.edc
$(AM_V_EDJ)$(EDJE_CC) $(EDJE_FLAGS) \
$(top_srcdir)/data/themes/default.edc \
$(top_builddir)/data/themes/default.edj
clean-local:
rm -f *.edj

1075
data/themes/default.edc

File diff suppressed because it is too large Load Diff

29
data/themes/images/Makefile.am

@ -0,0 +1,29 @@
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = \
pm_fill.png \
pm_overlay.png \
pm_shadow.png \
glow_exclam.png \
icon_eject.png \
icon_forward.png \
icon_mute.png \
icon_next.png \
icon_pause.png \
icon_play.png \
icon_prev.png \
icon_rewind.png \
icon_stop.png \
icon_volume.png \
icon_refresh.png \
icon_arrow_right.png \
horizontal_separated_bar_small_glow.png \
vgrad_shadow_bi.png \
pos_indicator.png \
icon_next2.png \
icon_prev2.png \
icon_play2.png \
icon_pause2.png \
icon_spanner.png \
icon_spanner2.png \
icon_volume2.png \
pos_indicator_big.png

BIN
data/themes/images/glow_exclam.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
data/themes/images/horizontal_separated_bar_small_glow.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

BIN
data/themes/images/icon_arrow_right.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
data/themes/images/icon_eject.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
data/themes/images/icon_forward.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
data/themes/images/icon_mute.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
data/themes/images/icon_next.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
data/themes/images/icon_next2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
data/themes/images/icon_pause.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
data/themes/images/icon_pause2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
data/themes/images/icon_play.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
data/themes/images/icon_play2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
data/themes/images/icon_prev.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
data/themes/images/icon_prev2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
data/themes/images/icon_refresh.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
data/themes/images/icon_rewind.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
data/themes/images/icon_spanner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
data/themes/images/icon_spanner2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
data/themes/images/icon_stop.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
data/themes/images/icon_volume.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
data/themes/images/icon_volume2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
data/themes/images/pm_fill.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

BIN
data/themes/images/pm_overlay.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
data/themes/images/pm_shadow.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
data/themes/images/pos_indicator.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

BIN
data/themes/images/pos_indicator_big.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
data/themes/images/vgrad_shadow_bi.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

47
m4/ac_attribute.m4

@ -0,0 +1,47 @@
dnl Copyright (C) 2004-2008 Kim Woelders
dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
dnl That code is public domain and can be freely used or copied.
dnl Originally snatched from somewhere...
dnl Macro for checking if the compiler supports __attribute__
dnl Usage: AC_C___ATTRIBUTE__
dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__
dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is
dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused))
dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is
dnl defined to nothing.
AC_DEFUN([AC_C___ATTRIBUTE__],
[
AC_MSG_CHECKING([for __attribute__])
AC_CACHE_VAL([ac_cv___attribute__],
[AC_TRY_COMPILE(
[
#include <stdlib.h>
int func(int x);
int foo(int x __attribute__ ((unused)))
{
exit(1);
}
],
[],
[ac_cv___attribute__="yes"],
[ac_cv___attribute__="no"]
)])
AC_MSG_RESULT($ac_cv___attribute__)
if test "x${ac_cv___attribute__}" = "xyes" ; then
AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__])
AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused])
else
AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused])
fi
])
dnl End of ac_attribute.m4

5
m4/efl_beta.m4

@ -0,0 +1,5 @@
dnl use: EFL_ENABLE_BETA_API_SUPPORT
AC_DEFUN([EFL_ENABLE_BETA_API_SUPPORT],
[
AC_DEFINE([EFL_BETA_API_SUPPORT], [1], [Enable access to unstable EFL API that are still in beta])
])

71
m4/efl_binary.m4

@ -0,0 +1,71 @@
dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
dnl That code is public domain and can be freely used or copied.
dnl Macro that check if a binary is built or not
dnl Usage: EFL_ENABLE_BIN(binary)
dnl Call AC_SUBST(BINARY_PRG) (BINARY is the uppercase of binary, - being transformed into _)
dnl Define have_binary (- is transformed into _)
dnl Define conditional BUILD_BINARY (BINARY is the uppercase of binary, - being transformed into _)
AC_DEFUN([EFL_ENABLE_BIN],
[
m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl
m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl
have_[]m4_defn([DOWN])="yes"
dnl configure option
AC_ARG_ENABLE([$1],
[AC_HELP_STRING([--disable-$1], [disable building of ]DOWN)],
[
if test "x${enableval}" = "xyes" ; then
have_[]m4_defn([DOWN])="yes"
else
have_[]m4_defn([DOWN])="no"
fi
])
AC_MSG_CHECKING([whether to build ]DOWN[ binary])
AC_MSG_RESULT([$have_[]m4_defn([DOWN])])
if test "x$have_[]m4_defn([DOWN])" = "xyes"; then
UP[]_PRG=DOWN[${EXEEXT}]
fi
AC_SUBST(UP[]_PRG)
AM_CONDITIONAL(BUILD_[]UP, test "x$have_[]m4_defn([DOWN])" = "xyes")
AS_IF([test "x$have_[]m4_defn([DOWN])" = "xyes"], [$2], [$3])
])
dnl Macro that check if a binary is built or not
dnl Usage: EFL_WITH_BIN(package, binary, default_value)
dnl Call AC_SUBST(_binary) (_binary is the lowercase of binary, - being transformed into _ by default, or the value set by the user)
AC_DEFUN([EFL_WITH_BIN],
[
m4_pushdef([DOWN], m4_translit([[$2]], [-A-Z], [_a-z]))dnl
dnl configure option
AC_ARG_WITH([$2],
[AC_HELP_STRING([--with-$2=PATH], [specify a specific path to ]DOWN[ @<:@default=$3@:>@])],
[_efl_with_binary=${withval}],
[_efl_with_binary=$(pkg-config --variable=prefix $1)/bin/$3])
DOWN=${_efl_with_binary}
AC_MSG_NOTICE(DOWN[ set to ${_efl_with_binary}])
with_binary_[]m4_defn([DOWN])=${_efl_with_binary}
AC_SUBST(DOWN)
])

6
m4/efl_eo.m4

@ -0,0 +1,6 @@
dnl use: EFL_ENABLE_EO_API_SUPPORT
AC_DEFUN([EFL_ENABLE_EO_API_SUPPORT],
[
AC_DEFINE([EFL_EO_API_SUPPORT], [1], [Enable access to unstable EFL Eo API])
])

33
pkgbuild/PKGBUILD.in

@ -0,0 +1,33 @@
# Maintainer: Enlightenment Developers <enlightenment-devel@enlightenment.org>
pkgname=rage
pkgver=@VERSION@
pkgrel=1
pkgdesc="Video player for Enlightenment - GIT development snapshot"
arch=('i686' 'x86_64' 'arm')
url="http://www.enlightenment.org"
license=('BSD')
depends=('elementary' 'efl')
options=('!libtool' 'debug')
build() {
cd "../.."
export CFLAGS="$CFLAGS -fvisibility=hidden -fomit-frame-pointer"
[[ -e Makefile ]] && make clean distclean
./configure --prefix=/usr
make
}
#check() {
# cd "../.."
# make -k check
#}
package() {
cd "../.."
make -j1 DESTDIR="$pkgdir/" install
install -Dm644 README "$pkgdir/usr/share/$pkgname/README"
install -Dm644 NEWS "$pkgdir/usr/share/$pkgname/NEWS"
install -Dm644 ChangeLog "$pkgdir/usr/share/$pkgname/ChangeLog"
install -Dm644 AUTHORS "$pkgdir/usr/share/$pkgname/AUTHORS"
install -Dm644 COPYING "$pkgdir/usr/share/licenses/$pkgname/COPYING"
ln -s ../licenses/$pkgname/COPYING "$pkgdir/usr/share/$pkgname/COPYING"
}

48
rage.spec.in

@ -0,0 +1,48 @@
%define _missing_doc_files_terminate_build 0
%{!?_rel:%{expand:%%global _rel 0.enl%{?dist}}}
Summary: EFL Video Player
Name: @PACKAGE@
Version: @VERSION@
Release: %{_rel}
License: BSD
Group: Applications/System
URL: http://www.enlightenment.org/
Source: http://download.enlightenment.org/releases/%{name}-%{version}.tar.gz
Packager: %{?_packager:%{_packager}}%{!?_packager:Michael Jennings <mej@eterm.org>}
Vendor: %{?_vendorinfo:%{_vendorinfo}}%{!?_vendorinfo:The Enlightenment Project (http://www.enlightenment.org/)}
Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
BuildRequires: elementary-devel, emotion-devel
BuildRoot: %{_tmppath}/%{name}-%{version}-root
%description
EFL Video Player
%prep
%setup -q
%build
%{configure} --prefix=%{_prefix}
%{__make} %{?_smp_mflags} %{?mflags}
%install
%{__make} %{?mflags_install} DESTDIR=$RPM_BUILD_ROOT install
%clean
test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT
%files
%defattr(-, root, root)
%doc AUTHORS COPYING README
%{_bindir}/%{name}
%{_datadir}/applications/%{name}.desktop
%{_datadir}/%{name}/
%{_datadir}/icons/%{name}.png
%changelog

2
src/Makefile.am

@ -0,0 +1,2 @@
MAINTAINERCLEANFILES = Makefile.in
SUBDIRS = bin

14
src/bin/Makefile.am

@ -0,0 +1,14 @@
AUTOMAKE_OPTIONS = subdir-objects
MAINTAINERCLEANFILES = Makefile.in
bin_PROGRAMS = rage
rage_CPPFLAGS = -I. \
-DPACKAGE_BIN_DIR=\"$(bindir)\" -DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" @RAGE_CFLAGS@
rage_LDADD = @RAGE_LIBS@
rage_SOURCES = \
main.c main.h \
video.c video.h

1013
src/bin/main.c

File diff suppressed because it is too large Load Diff

6
src/bin/main.h

@ -0,0 +1,6 @@
#ifndef _MAIN_H__
#define _MAIN_H__ 1
#include "rage_config.h"
#endif

828
src/bin/video.c

@ -0,0 +1,828 @@
#include <Elementary.h>
#include <Emotion.h>
#include "video.h"
#include "rage_config.h"
typedef struct _Video Video;
struct _Video
{
Evas_Object_Smart_Clipped_Data __clipped_data;
Evas_Object *clip, *o_vid, *o_event;
Ecore_Timer *smooth_timer;
Ecore_Job *restart_job;
const char *file;
int w, h;
int iw, ih, piw, pih;
int resizes;
struct {
Evas_Coord x, y;
Eina_Bool down : 1;
} down;
Eina_Bool nosmooth : 1;
Eina_Bool loop : 1;
Eina_Bool fill : 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 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;
// double len, pos;
if (!sd) return;
evas_object_geometry_get(data, &ox, &oy, &ow, &oh);
evas_object_show(sd->o_vid);
evas_object_show(sd->clip);
_ob_resize(data, ox, oy, ow, oh);
// len = emotion_object_play_length_get(sd->o_vid);
// pos = emotion_object_position_get(sd->o_vid);
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_vid_len_change(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
Video *sd = evas_object_smart_data_get(data);
if (!sd) return;
}
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);
}
else
{
sd->restart_job = NULL;
evas_object_smart_callback_call(data, "stop", NULL);
}
}
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);
// DBG("progress: '%s' '%3.3f",
// emotion_object_progress_info_get(sd->o_vid),
// emotion_object_progress_status_get(sd->o_vid));
}
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);
// DBG("ref: '%s' num '%i'",
// emotion_object_ref_file_get(sd->o_vid),
// emotion_object_ref_num_get(sd->o_vid));
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
}
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_smart_member_add(o, obj);
sd->clip = o;
evas_object_color_set(o, 255, 255, 255, 255);
}
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->clip) evas_object_del(sd->clip);
if (sd->o_vid) evas_object_del(sd->o_vid);
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);
_parent_sc.del(obj);
}
static void
_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
{
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 == w) && (oh == h)) return;
evas_object_smart_changed(obj);
evas_object_resize(sd->clip, ow, oh);
}
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);
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);
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
_smart_move(Evas_Object *obj, Evas_Coord x EINA_UNUSED, Evas_Coord y EINA_UNUSED)
{
Video *sd = evas_object_smart_data_get(obj);
if (!sd) return;
evas_object_smart_changed(obj);
}
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.move = _smart_move;
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;
char *modules[] =
{
NULL,
"gstreamer",
"xine",
"vlc",
"gstreamer1"
};
char *mod = NULL;
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);
mod = modules[4];
if (!emotion_object_init(o, mod))
{
evas_object_del(sd->o_vid);
sd->o_vid = NULL;
return obj;
}
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, "length_change", _cb_vid_len_change, 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);
evas_object_raise(sd->o_event);
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)
{
Video *sd = evas_object_smart_data_get(obj);
if (!sd) return;
evas_object_hide(sd->o_vid);
evas_object_hide(sd->clip);
eina_stringshare_replace(&(sd->file), file);
emotion_object_file_set(sd->o_vid, sd->file);
video_position_set(obj, 0.0);
}
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);
}
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;
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_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);