From 10d294a3a3ea38da4c60d540000835517733d071 Mon Sep 17 00:00:00 2001 From: raster Date: Thu, 30 Aug 2012 09:54:57 +0000 Subject: [PATCH] EFL 1.7 svn doobies git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/branches/emotion-1.7@75862 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- .gitignore | 91 + AUTHORS | 10 + COPYING | 25 + ChangeLog | 48 + INSTALL | 14 + Makefile.am | 52 + NEWS | 24 + README | 22 + TODO | 27 + autogen.sh | 39 + configure.ac | 370 ++ data/Makefile.am | 57 + data/bpause.png | Bin 0 -> 383 bytes data/bplay.png | Bin 0 -> 425 bytes data/bstop.png | Bin 0 -> 401 bytes data/e_logo.png | Bin 0 -> 7833 bytes data/fr1.png | Bin 0 -> 591 bytes data/fr2.png | Bin 0 -> 288 bytes data/fr3.png | Bin 0 -> 657 bytes data/fr4.png | Bin 0 -> 375 bytes data/fr5.png | Bin 0 -> 1366 bytes data/fr6.png | Bin 0 -> 699 bytes data/fr7.png | Bin 0 -> 1184 bytes data/h_slider.png | Bin 0 -> 917 bytes data/icon.edc | 14 + data/knob.png | Bin 0 -> 1076 bytes data/orb.png | Bin 0 -> 203 bytes data/pnl.png | Bin 0 -> 705 bytes data/sl.png | Bin 0 -> 225 bytes data/theme.edc | 1667 +++++++++ data/tiles.png | Bin 0 -> 3026 bytes data/video_frame_bottom.png | Bin 0 -> 514 bytes data/video_frame_left.png | Bin 0 -> 2023 bytes data/video_frame_right.png | Bin 0 -> 2441 bytes data/video_frame_top.png | Bin 0 -> 471 bytes data/whb.png | Bin 0 -> 207 bytes data/window_inner_shadow.png | Bin 0 -> 30426 bytes doc/Doxyfile.in | 138 + doc/Makefile.am | 33 + doc/e.css | 273 ++ doc/emotion.css | 178 + doc/examples.dox | 104 + doc/foot.html | 18 + doc/head.html | 68 + doc/img/e.png | Bin 0 -> 30052 bytes doc/img/edoxy.css | 486 +++ doc/img/emotion_ratio.eps | 4541 +++++++++++++++++++++++++ doc/img/emotion_ratio.png | Bin 0 -> 12950 bytes doc/img/foot_bg.png | Bin 0 -> 173 bytes doc/img/head_bg.png | Bin 0 -> 214 bytes doc/img/header_menu_background.png | Bin 0 -> 192 bytes doc/img/header_menu_background_last.png | Bin 0 -> 637 bytes doc/img/header_menu_current_background.png | Bin 0 -> 1200 bytes doc/img/header_menu_unselected_background.png | Bin 0 -> 1596 bytes doc/img/logo.png | Bin 0 -> 3825 bytes emotion.pc.in | 11 + emotion.spec.in | 79 + m4/ac_attribute.m4 | 46 + m4/efl_binary.m4 | 44 + m4/efl_doxygen.m4 | 94 + m4/efl_edje_external.m4 | 56 + m4/efl_examples.m4 | 63 + m4/efl_shm_open.m4 | 69 + m4/emotion_check.m4 | 216 ++ m4/gst-element-check.m4 | 23 + src/Makefile.am | 12 + src/bin/Makefile.am | 26 + src/bin/emotion_test_main.c | 748 ++++ src/edje_external/Makefile.am | 18 + src/edje_external/emotion.c | 516 +++ src/examples/Makefile.am | 39 + src/examples/emotion_basic_example.c | 81 + src/examples/emotion_border_example.c | 238 ++ src/examples/emotion_generic_example.c | 233 ++ src/examples/emotion_signals_example.c | 173 + src/generic_players/Makefile.am | 8 + src/generic_players/vlc/Makefile.am | 18 + src/generic_players/vlc/emotion_generic_vlc.c | 873 +++++ src/lib/Emotion.h | 1282 +++++++ src/lib/Makefile.am | 59 + src/lib/emotion_main.c | 484 +++ src/lib/emotion_private.h | 135 + src/lib/emotion_smart.c | 2110 ++++++++++++ src/modules/Makefile.am | 4 + src/modules/generic/Emotion_Generic_Plugin.h | 144 + src/modules/generic/Makefile.am | 31 + src/modules/generic/README | 79 + src/modules/generic/emotion_generic.c | 1794 ++++++++++ src/modules/generic/emotion_generic.h | 112 + src/modules/gstreamer/Makefile.am | 37 + src/modules/gstreamer/emotion_alloc.c | 91 + src/modules/gstreamer/emotion_convert.c | 252 ++ src/modules/gstreamer/emotion_fakeeos.c | 71 + src/modules/gstreamer/emotion_gstreamer.c | 2130 ++++++++++++ src/modules/gstreamer/emotion_gstreamer.h | 330 ++ src/modules/gstreamer/emotion_sink.c | 1316 +++++++ src/modules/xine/Makefile.am | 31 + src/modules/xine/emotion_xine.c | 1723 ++++++++++ src/modules/xine/emotion_xine.h | 98 + src/modules/xine/emotion_xine_vo_out.c | 766 +++++ 100 files changed, 25062 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 TODO create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 data/Makefile.am create mode 100644 data/bpause.png create mode 100644 data/bplay.png create mode 100644 data/bstop.png create mode 100644 data/e_logo.png create mode 100644 data/fr1.png create mode 100644 data/fr2.png create mode 100644 data/fr3.png create mode 100644 data/fr4.png create mode 100644 data/fr5.png create mode 100644 data/fr6.png create mode 100644 data/fr7.png create mode 100644 data/h_slider.png create mode 100644 data/icon.edc create mode 100644 data/knob.png create mode 100644 data/orb.png create mode 100644 data/pnl.png create mode 100644 data/sl.png create mode 100644 data/theme.edc create mode 100644 data/tiles.png create mode 100644 data/video_frame_bottom.png create mode 100644 data/video_frame_left.png create mode 100644 data/video_frame_right.png create mode 100644 data/video_frame_top.png create mode 100644 data/whb.png create mode 100644 data/window_inner_shadow.png create mode 100644 doc/Doxyfile.in create mode 100644 doc/Makefile.am create mode 100644 doc/e.css create mode 100644 doc/emotion.css create mode 100644 doc/examples.dox create mode 100644 doc/foot.html create mode 100644 doc/head.html create mode 100644 doc/img/e.png create mode 100644 doc/img/edoxy.css create mode 100644 doc/img/emotion_ratio.eps create mode 100644 doc/img/emotion_ratio.png create mode 100644 doc/img/foot_bg.png create mode 100644 doc/img/head_bg.png create mode 100644 doc/img/header_menu_background.png create mode 100644 doc/img/header_menu_background_last.png create mode 100644 doc/img/header_menu_current_background.png create mode 100644 doc/img/header_menu_unselected_background.png create mode 100644 doc/img/logo.png create mode 100644 emotion.pc.in create mode 100644 emotion.spec.in create mode 100644 m4/ac_attribute.m4 create mode 100644 m4/efl_binary.m4 create mode 100644 m4/efl_doxygen.m4 create mode 100644 m4/efl_edje_external.m4 create mode 100644 m4/efl_examples.m4 create mode 100644 m4/efl_shm_open.m4 create mode 100644 m4/emotion_check.m4 create mode 100644 m4/gst-element-check.m4 create mode 100644 src/Makefile.am create mode 100644 src/bin/Makefile.am create mode 100644 src/bin/emotion_test_main.c create mode 100644 src/edje_external/Makefile.am create mode 100644 src/edje_external/emotion.c create mode 100644 src/examples/Makefile.am create mode 100644 src/examples/emotion_basic_example.c create mode 100644 src/examples/emotion_border_example.c create mode 100644 src/examples/emotion_generic_example.c create mode 100644 src/examples/emotion_signals_example.c create mode 100644 src/generic_players/Makefile.am create mode 100644 src/generic_players/vlc/Makefile.am create mode 100644 src/generic_players/vlc/emotion_generic_vlc.c create mode 100644 src/lib/Emotion.h create mode 100644 src/lib/Makefile.am create mode 100644 src/lib/emotion_main.c create mode 100644 src/lib/emotion_private.h create mode 100644 src/lib/emotion_smart.c create mode 100644 src/modules/Makefile.am create mode 100644 src/modules/generic/Emotion_Generic_Plugin.h create mode 100644 src/modules/generic/Makefile.am create mode 100644 src/modules/generic/README create mode 100644 src/modules/generic/emotion_generic.c create mode 100644 src/modules/generic/emotion_generic.h create mode 100644 src/modules/gstreamer/Makefile.am create mode 100644 src/modules/gstreamer/emotion_alloc.c create mode 100644 src/modules/gstreamer/emotion_convert.c create mode 100644 src/modules/gstreamer/emotion_fakeeos.c create mode 100644 src/modules/gstreamer/emotion_gstreamer.c create mode 100644 src/modules/gstreamer/emotion_gstreamer.h create mode 100644 src/modules/gstreamer/emotion_sink.c create mode 100644 src/modules/xine/Makefile.am create mode 100644 src/modules/xine/emotion_xine.c create mode 100644 src/modules/xine/emotion_xine.h create mode 100644 src/modules/xine/emotion_xine_vo_out.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84d4b2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,91 @@ +*.o +*.swp +*.swo +*~ +ABOUT-NLS +Makefile +Makefile.in +aclocal.m4 +autom4te.cache/ +config.cache +config.cache-env +config.guess +config.h +config.h.in +config.log +config.status +config.sub +configure +data/Makefile +data/Makefile.in +data/icon.edj +data/theme.edj +depcomp +doc/Doxyfile +doc/Makefile +doc/Makefile.in +emotion.pc +emotion.spec +install-sh +libtool +ltmain.sh +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +missing +src/Makefile +src/Makefile.in +src/bin/.deps/ +src/bin/.libs/ +src/bin/Makefile +src/bin/Makefile.in +src/bin/emotion_test +src/edje_external/.deps/ +src/edje_external/.libs/ +src/edje_external/Makefile +src/edje_external/Makefile.in +src/edje_external/module.la +src/edje_external/module_la-emotion.lo +src/examples/.deps/ +src/examples/Makefile +src/examples/Makefile.in +src/generic_players/Makefile +src/generic_players/Makefile.in +src/generic_players/vlc/.deps/ +src/generic_players/vlc/Makefile +src/generic_players/vlc/Makefile.in +src/lib/.deps/ +src/lib/.libs/ +src/lib/Makefile +src/lib/Makefile.in +src/lib/emotion_main.lo +src/lib/emotion_smart.lo +src/lib/libemotion.la +src/modules/Makefile +src/modules/Makefile.in +src/modules/generic/.deps/ +src/modules/generic/.libs/ +src/modules/generic/Makefile +src/modules/generic/Makefile.in +src/modules/generic/em_generic.la +src/modules/generic/em_generic_la-emotion_generic.lo +src/modules/gstreamer/.deps/ +src/modules/gstreamer/.libs/ +src/modules/gstreamer/Makefile +src/modules/gstreamer/Makefile.in +src/modules/gstreamer/gstreamer.la +src/modules/gstreamer/gstreamer_la-emotion_alloc.lo +src/modules/gstreamer/gstreamer_la-emotion_convert.lo +src/modules/gstreamer/gstreamer_la-emotion_fakeeos.lo +src/modules/gstreamer/gstreamer_la-emotion_gstreamer.lo +src/modules/gstreamer/gstreamer_la-emotion_sink.lo +src/modules/xine/.deps/ +src/modules/xine/.libs/ +src/modules/xine/Makefile +src/modules/xine/Makefile.in +src/modules/xine/xine.la +src/modules/xine/xine_la-emotion_xine.lo +src/modules/xine/xine_la-emotion_xine_vo_out.lo +stamp-h1 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..c2579a8 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,10 @@ +Carsten Haitzler +Vincent Torri +Nicolas Aguirre +Sebastian Dransfeld +Cedric Bail +Rafael Antognolli +Jérôme Pinot +Pierre Le Magourou +Hugo Camboulive +Sohyun Kim diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..aab8362 --- /dev/null +++ b/COPYING @@ -0,0 +1,25 @@ +Copyright notice for Emotion: + +Copyright (C) 2004-2011 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. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..c85115a --- /dev/null +++ b/ChangeLog @@ -0,0 +1,48 @@ +2012-04-26 Carsten Haitzler (The Rasterman) + + * 1.0.0 release + +2012-04-30 Jérôme Pinot + + * Fix build out of tree. + +2012-05-16 Carsten Haitzler (The Rasterman) + + * Fix emotion video overlay support to detect correct engine name. + +2012-06-07 Cedric Bail + + * Fix stride for all YUV video stream. + +2012-06-08 Pierre Le Magourou + + * Add support for "playback_started" callback to generic player. + +2012-06-08 Hugo Camboulive + + * Implement SPU switch for generic/vlc. + +2012-06-19 Cedric Bail + + * Sync rendering with Ecore_Animator. + +2012-07-03 Cedric Bail + + * Track pending object for proper shutdown. + +2012-06-05 Sohyun Kim + + * Add fimcconvert element to resize and convert color using fimc on device. + +2012-08-01 Cedric Bail + + * Fix race condition in gstreamer render function. + +2012-08-10 Sohyun Kim + + * Fix priority set/get for gstreamer. + +2012-08-28 Cedric Bail + + * Reset VLC pipeline on EOS. + * Fix a race condition on shutdown when still saving a file position. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..374b488 --- /dev/null +++ b/INSTALL @@ -0,0 +1,14 @@ +COMPILING and INSTALLING: + +If you got a official release tar archive do: + ./configure + +( otherwise if you got this from enlightenment cvs do: ./autogen.sh ) + +Then to compile: + make + +To install (run this as root, or the user who handles installs): + make install + +NOTE: You MUST make install Emotion for it to run properly. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..248f9bd --- /dev/null +++ b/Makefile.am @@ -0,0 +1,52 @@ +## Process this file with automake to produce Makefile.in + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = src data doc + +MAINTAINERCLEANFILES = \ +Makefile.in \ +aclocal.m4 \ +config.guess \ +config.h.in \ +config.sub \ +configure \ +depcomp \ +install-sh \ +ltconfig \ +ltmain.sh \ +missing \ +mkinstalldirs \ +stamp-h.in \ +$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz \ +$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.bz2 \ +$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc.tar.bz2 + +EXTRA_DIST = \ +README \ +AUTHORS \ +COPYING \ +autogen.sh \ +emotion.spec \ +emotion.spec.in \ +emotion.pc.in \ +m4/ac_attribute.m4 \ +m4/efl_binary.m4 \ +m4/efl_doxygen.m4 \ +m4/efl_edje_external.m4 \ +m4/efl_examples.m4 \ +m4/efl_shm_open.m4 \ +m4/emotion_check.m4 \ +m4/gst-element-check.m4 + + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = emotion.pc + +.PHONY: doc + +# Documentation + +doc: + @echo "entering doc/" + make -C doc doc diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..cedcaf4 --- /dev/null +++ b/NEWS @@ -0,0 +1,24 @@ +Emotion 1.7.0 + +Changes since Emotion 1.0.0: +------------------------- + +Additions: + - Add support for "playback_started" callback to generic player. + - Implement SPU switch for generic/vlc. + - Sync rendering with Ecore_Animator. + - Track pending object for proper shutdown. + - Start handling embedded hardware customization. + +Fixes: + - build out of tree. + - stride of all YUV video + - fix race condition in gstreamer render function on shutdown and file set. + - fix priority set/get for gstreamer. + - reset VLC pipeline on EOS. + - fix race condition on shutdown when still saving a file position. + +Improvements: + +Removal: + diff --git a/README b/README new file mode 100644 index 0000000..b652358 --- /dev/null +++ b/README @@ -0,0 +1,22 @@ +Emotion 1.7.0 + +****************************************************************************** + + FOR ANY ISSUES PLEASE EMAIL: + enlightenment-devel@lists.sourceforge.net + +****************************************************************************** + +Emotion is a video (and audio) codec playback library that acts as a +front-end to libxine or gstreamer (or something else more generic) +that provides and evas object as a control object and video output +point. It makes using video API's much simpler and easier while it's +at it. + +------------------------------------------------------------------------------ +COMPILING AND INSTALLING: + + ./configure + make +(do this as root unless you are installing in your users directories): + make install diff --git a/TODO b/TODO new file mode 100644 index 0000000..cfe45c2 --- /dev/null +++ b/TODO @@ -0,0 +1,27 @@ + +Emotion smart object +-------------------- + + +Xine module +----------- + +* Fix seek and get_pos threads delete bugs (infinite loop) +* Add support of visualizations for audio files (Goom...) + + +Gstreamer module +---------------- + +* Add gststreamselector to support multiple video and audio streams. +* Add API for visualisation plugins +* Add http source (N. Aguirre) +* Add mms source +* Add rtsp source +* Add dvb source +* Add v4l2 source (no v4l1 source) (N. Aguirre) +* Add dvd source (waiting for the dvdnav gstreamer source plugin, though...) +* Add daap source +* Add upnp source +* Implement time shifting +* Add evas sink to gstreamer (in progress: V. Torri) diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..00116ea --- /dev/null +++ b/autogen.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +rm -rf autom4te.cache +rm -f aclocal.m4 ltmain.sh + +touch README +touch ABOUT-NLS + +echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || 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 + +W=0 + +rm -f config.cache-env.tmp +echo "OLD_PARM=\"$@\"" >> config.cache-env.tmp +echo "OLD_CFLAGS=\"$CFLAGS\"" >> config.cache-env.tmp +echo "OLD_PATH=\"$PATH\"" >> config.cache-env.tmp +echo "OLD_PKG_CONFIG_PATH=\"$PKG_CONFIG_PATH\"" >> config.cache-env.tmp +echo "OLD_LDFLAGS=\"$LDFLAGS\"" >> config.cache-env.tmp + +cmp config.cache-env.tmp config.cache-env >> /dev/null +if [ $? -ne 0 ]; then + W=1; +fi + +if [ $W -ne 0 ]; then + echo "Cleaning configure cache..."; + rm -f config.cache config.cache-env + mv config.cache-env.tmp config.cache-env +else + rm -f config.cache-env.tmp +fi + +if [ -z "$NOCONFIGURE" ]; then + ./configure -C "$@" +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..9cc0537 --- /dev/null +++ b/configure.ac @@ -0,0 +1,370 @@ +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +m4_define([v_maj], [1]) +m4_define([v_min], [7]) +m4_define([v_mic], [0]) +m4_define([v_rev], m4_esyscmd([(svnversion "${SVN_REPO_PATH:-.}" | grep -v '\(export\|Unversioned directory\)' || echo 0) | awk -F : '{printf("%s\n", $1);}' | tr -d ' :MSP\n'])) +m4_if(v_rev, [0], [m4_define([v_rev], m4_esyscmd([git log 2> /dev/null | (grep -m1 git-svn-id || echo 0) | sed -e 's/.*@\([0-9]*\).*/\1/' | tr -d '\n']))]) +##-- When released, remove the dnl on the below line +m4_undefine([v_rev]) +##-- When doing snapshots - change soname. remove dnl on below line +m4_define([relname], [ver-pre-svn-07]) +m4_define([v_rel], [-release relname]) +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +m4_ifdef([v_rev], [m4_define([v_ver], [v_maj.v_min.v_mic.v_rev])], +[m4_define([v_ver], [v_maj.v_min.v_mic])]) +m4_define([lt_rev], m4_eval(v_maj + v_min)) +m4_define([lt_cur], v_mic) +m4_define([lt_age], v_min) +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## + +AC_INIT([emotion], [v_ver], [enlightenment-devel@lists.sourceforge.net]) +AC_PREREQ([2.60]) +AC_CONFIG_SRCDIR([configure.ac]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_ISC_POSIX + +AM_INIT_AUTOMAKE([1.6 dist-bzip2]) +AM_CONFIG_HEADER([config.h]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_LIBTOOL_WIN32_DLL +define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl +define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl +AC_PROG_LIBTOOL + +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +m4_ifdef([v_rev], , [m4_define([v_rev], [0])]) +m4_ifdef([v_rel], , [m4_define([v_rel], [])]) +AC_DEFINE_UNQUOTED(VMAJ, [v_maj], [Major version]) +AC_DEFINE_UNQUOTED(VMIN, [v_min], [Minor version]) +AC_DEFINE_UNQUOTED(VMIC, [v_mic], [Micro version]) +AC_DEFINE_UNQUOTED(VREV, [v_rev], [Revison]) +version_info="lt_rev:lt_cur:lt_age" +release_info="v_rel" +AC_SUBST(version_info) +AC_SUBST(release_info) +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +VMAJ=v_maj +AC_SUBST(VMAJ) + +want_generic="yes" +case "$host_os" in + mingw*) + want_xine="no" + want_gstreamer="yes" + want_generic="no" + want_generic_vlc="no" + ;; + *) + want_xine="yes" + want_gstreamer="yes" + want_generic_vlc="yes" + ;; +esac + +requirement_emotion="" + +### Additional options to configure + +EFL_ENABLE_BIN([emotion-test]) + +# edje_cc + +AC_ARG_WITH([edje-cc], + [AC_HELP_STRING([--with-edje-cc=PATH], [specify a specific path to edje_cc])], + [ + v=$withval; + edje_cc=$v + echo " Enlightenment edje_cc explicitly set to "$edje_cc; + ], + [edje_cc=$(pkg-config --variable=prefix edje)/bin/edje_cc]) +AC_SUBST(edje_cc) + + +### Checks for programs +AC_PROG_CC + +# pkg-config +PKG_PROG_PKG_CONFIG + +# Check whether pkg-config supports Requires.private +if $PKG_CONFIG --atleast-pkgconfig-version 0.22; then + pkgconfig_requires_private="Requires.private" +else + pkgconfig_requires_private="Requires" +fi +AC_SUBST(pkgconfig_requires_private) + +# doxygen program for documentation building + +EFL_CHECK_DOXYGEN([build_doc="yes"], [build_doc="no"]) + + +### Checks for libraries + +requirement_emotion="ecore >= 1.6.99 evas >= 1.6.99 eet >= 1.6.99 eina >= 1.6.99" +PKG_CHECK_MODULES(EMOTION, [${requirement_emotion}]) + + +if test "x${have_emotion_test}" = "xyes" ; then + PKG_CHECK_MODULES(EMOTION_BIN, [eina >= 1.6.99 evas >= 1.6.99 ecore >= 1.6.99 ecore-evas >= 1.6.99 edje >= 1.6.99]) +fi + +PKG_CHECK_MODULES(ECORE_X, [ecore-x >= 1.6.99 ecore-evas >= 1.6.99], [have_ecore_x="yes"], [have_ecore_x="no"]) + +PKG_CHECK_MODULES(ECORE_FB, [ecore-fb >= 1.6.99], [have_ecore_fb="yes"], [have_ecore_fb="no"]) + +if test "x${have_ecore_x}" = "xyes" ; then + AC_DEFINE(EMOTION_HAVE_ECORE_X, 1, [Define to 1 if Ecore_X is enabled]) +fi + +if test "x${have_ecore_fb}" = "xyes" ; then + AC_DEFINE(EMOTION_HAVE_ECORE_FB, 1, [Define to 1 if Ecore_Fb is enabled]) +fi + +PKG_CHECK_EXISTS([evas-software-x11 >= 1.6.99], [AC_DEFINE(HAVE_EVAS_SOFWARE_X11, 1, [Evas Software Xlib Engine Support])]) + +PKG_CHECK_EXISTS([evas-xrender-x11 >= 1.6.99], [AC_DEFINE(HAVE_EVAS_XRENDER_X11, 1, [Evas Software Xlib Engine Support])]) + +PKG_CHECK_EXISTS([evas-opengl-x11 >= 1.6.99], [AC_DEFINE(HAVE_EVAS_OPENGL_X11, 1, [Evas OpenGL Xlib Engine Support])]) + +PKG_CHECK_EXISTS([evas-fb >= 1.6.99], [AC_DEFINE(HAVE_EVAS_FB, 1, [Evas Framebuffer Engine Support])]) + +EFL_EDJE_EXTERNAL([have_edje_external="yes"], [have_edje_external="no"]) + +PKG_CHECK_MODULES(EEZE, [eeze >= 1.6.99], [have_eeze="yes"], [have_eeze="no"]) + +if test "x${have_eeze}" = "xyes"; then + AC_DEFINE(EMOTION_HAVE_EEZE, 1, [Define to 1 if Eeze is available]) + requirement_emotion="${requirement_emotion} eeze >= 1.6.99" +fi + +PKG_CHECK_MODULES([EIO], [eio >= 1.6.99], [have_eio="yes"], [have_eio="no"]) +if test "x${have_eio}" = "xyes"; then + AC_DEFINE(HAVE_EIO, 1, [Use EIO for asynchronous file access]) + requirement_emotion="eio >= 1.6.99 ${requirement_emotion}" +fi + +AM_CONDITIONAL([HAVE_EIO], [test "x${have_eio}" = "xyes"]) + +# ecore-x availability, used for XV, VAAPI, VDPAU output. + +have_ecore_x="no" +AC_ARG_ENABLE([ecore-x], + [AC_HELP_STRING([--disable-ecore-x], [disable ecore-x support. @<:@default=detect@:>@])], + [ + if test "x${enableval}" = "xyes" || test "x${enableval}" = "xauto" ; then + want_ecore_x=${enableval} + else + want_ecore_x="no" + fi + ], + [want_ecore_x="auto"]) + +if ! test "x$want_ecore_x" = "xno" ; then + PKG_CHECK_MODULES([ECORE_X], + [ecore-x >= 1.6.99], + [ + AC_DEFINE(HAVE_ECORE_X, 1, [X11 support for Ecore]) + have_ecore_x="yes" + requirement_elm="ecore-x >= 1.6.99 ${requirement_elm}" + ], + [have_ecore_x="no"] + ) +else + have_ecore_x="no" +fi + +if test "x$want_ecore_x" = "xyes" && test "x$have_ecore_x" = "xno" ; then + AC_MSG_ERROR([ecore-x support requested, but not found by pkg-config.]) +fi + +### Checks for header files + +AC_CHECK_HEADERS([unistd.h]) + +# Check for video4linux + +AC_MSG_CHECKING([for V4L2]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[ +fprintf(stdout, "%i\n", V4L2_CAP_VIDEO_CAPTURE); + ]])], + [ + AC_DEFINE(HAVE_V4L2, 1, [Define to 1 if you have Video4Linux 2 available]) + have_v4l2="yes" + ], + [have_v4l2="no"]) +AC_MSG_RESULT([${have_v4l2}]) + +### Checks for types + + +### Checks for structures + + +### Checks for compiler characteristics +AC_C_BIGENDIAN +AC_C___ATTRIBUTE__ + +EFL_EMOTION_BUILD="" +case "$host_os" in + mingw32ce*) + EMOTION_CPPFLAGS="-D_WIN32_WCE=0x0420" + EFL_EMOTION_BUILD="-DEFL_EMOTION_BUILD" + ;; + mingw*) + EMOTION_CPPFLAGS="-D_WIN32_WINNT=0x0501" + EFL_EMOTION_BUILD="-DEFL_EMOTION_BUILD" + ;; +esac +AC_SUBST(EFL_EMOTION_BUILD) +AC_SUBST(EMOTION_CPPFLAGS) + + +### Checks for linker characteristics + +# use --enable-auto-import on Windows + +lt_enable_auto_import="" +case "$host_os" in + mingw*) + lt_enable_auto_import="-Wl,--enable-auto-import" + ;; +esac +AC_SUBST(lt_enable_auto_import) + + +### Checks for library functions +AC_FUNC_ALLOCA + + +### Modules + +EMOTION_CHECK_MODULE([Xine], [${want_xine}]) +EMOTION_CHECK_MODULE([Gstreamer], [${want_gstreamer}]) +EMOTION_CHECK_MODULE([Generic], [${want_generic}]) + +EMOTION_CHECK_GENERIC_PLAYER([VLC], [${want_generic_vlc}]) + +if test "x${enable_xine}" = "xno" && test "x${enable_gstreamer}" = "xno" && test "x${enable_generic}" = "xno" ; then + AC_MSG_ERROR([Xine, Gstreamer or Generic backends must be selected to build Emotion]) +fi + +# Check if gstreamer X Overlay is available +build_xoverlay="no" +if test "x${enable_gstreamer}" = "xyes" ; then + PKG_CHECK_MODULES([GSTREAMER_INTERFACE], + [gstreamer-interfaces-0.10 >= 0.10.34], + [build_xoverlay="yes"], + [build_xoverlay="no"]) + if test "x${build_xoverlay}" = "xyes" ; then + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS ${GSTREAMER_CFLAGS} ${GSTREAMER_INTERFACE_CFLAGS}" + AC_CHECK_HEADER([gst/interfaces/xoverlay.h], + [ + AC_DEFINE(HAVE_XOVERLAY_H, 1, [Build with Gstreamer Xoverlay support]) + build_xoverlay="yes" + ], + [build_xoverlay="no"]) + CPPFLAGS=$save_CPPFLAGS + + save_LDFLAGS=${LDFLAGS} + LDFLAGS="${LDFLAGS} ${GSTREAMER_INTERFACES}" + AC_CHECK_LIB([gstinterfaces-0.10], + [gst_x_overlay_set_window_handle], + [AC_DEFINE([HAVE_X_OVERLAY_SET], [1], [Use gst_x_overlay_set_window_handle instead of old deprecated gst_x_overlay_set_xwindow_id])]) + LDFLAGS=$sava_LDFLAGS + fi +fi + +### install and build examples + +EFL_CHECK_BUILD_EXAMPLES([enable_build_examples="yes"], [enable_build_examples="no"]) +EFL_CHECK_INSTALL_EXAMPLES([enable_install_examples="yes"], [enable_install_examples="no"]) + +AC_SUBST(requirement_emotion) + +AC_OUTPUT([ +Makefile +emotion.pc +emotion.spec +src/Makefile +src/lib/Makefile +src/modules/Makefile +src/modules/xine/Makefile +src/modules/gstreamer/Makefile +src/modules/generic/Makefile +src/edje_external/Makefile +src/generic_players/Makefile +src/generic_players/vlc/Makefile +src/bin/Makefile +src/examples/Makefile +doc/Makefile +doc/Doxyfile +data/Makefile +]) + + +##################################################################### +## Info + +echo +echo +echo +echo "------------------------------------------------------------------------" +echo "$PACKAGE $VERSION" +echo "------------------------------------------------------------------------" +echo +echo "Configuration Options Summary:" +echo +echo " Modules:" +echo " Xine...............: ${enable_xine}" +echo " Gstreamer..........: ${enable_gstreamer} (X: ${have_ecore_x}/${build_xoverlay})" +echo " Generic............: ${enable_generic}" + +if test "x${enable_generic}" = "xyes" || test "x${enable_generic}" = "xstatic"; then +echo +echo " Generic Players:" +echo " VLC................: ${enable_generic_vlc}" +fi + +echo +echo " Build emotion_test...: $have_emotion_test" +echo " edje_cc..............: ${edje_cc}" +echo +echo " Edje EXTERNAL support: ${have_edje_external}" +echo +echo " Eio..................: ${have_eio}" +echo " V4L2.................: ${have_v4l2}" +echo +echo "Documentation..........: ${build_doc}" +echo "Examples.............: ${enable_build_examples}" +echo "Examples installed...: ${enable_install_examples}" +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" +echo +if test "x${have_static_module}" = "xyes" ; then +echo -e "\0033\01331;31mWarning\0033\01331;0m: You are trying to link statically one or more modules to Emotion." +echo " You must know what you are doing, or else you will have a lot of problems." +echo " And asparagus will disappear from the earth." +echo " Think about that." +echo +fi diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 0000000..db772b1 --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,57 @@ + +MAINTAINERCLEANFILES = Makefile.in + +EDJE_CC = @edje_cc@ +EDJE_FLAGS = -v -id $(top_srcdir)/data -fd $(top_srcdir)/data + +filesdir = $(datadir)/$(PACKAGE)/data + +files_DATA = + +if BUILD_EMOTION_TEST +files_DATA += theme.edj +endif + +if ENABLE_EDJE_EXTERNAL +files_DATA += icon.edj +endif + +EXTRA_DIST = \ +bpause.png \ +bplay.png \ +bstop.png \ +e_logo.png \ +fr1.png \ +fr2.png \ +fr3.png \ +fr4.png \ +fr5.png \ +fr6.png \ +fr7.png \ +h_slider.png \ +knob.png \ +orb.png \ +pnl.png \ +sl.png \ +tiles.png \ +video_frame_bottom.png \ +video_frame_left.png \ +video_frame_right.png \ +video_frame_top.png \ +whb.png \ +window_inner_shadow.png \ +theme.edc \ +icon.edc + +theme.edj: Makefile + $(EDJE_CC) $(EDJE_FLAGS) \ + $(top_srcdir)/data/theme.edc \ + $(top_builddir)/data/theme.edj + +icon.edj: Makefile + $(EDJE_CC) $(EDJE_FLAGS) \ + $(top_srcdir)/data/icon.edc \ + $(top_builddir)/data/icon.edj + +clean-local: + rm -f *.edj diff --git a/data/bpause.png b/data/bpause.png new file mode 100644 index 0000000000000000000000000000000000000000..e82754515756043e1b13a9e3323973768cf0d67f GIT binary patch literal 383 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fY)RhkE*VulybYZl&*#L3-aT{Y zOiZZl^EXP53NL=({=ng*^k~(q`%6}R=U!&3 z&d6-&b9>eBdXvu8hJ(Ax4y4X|p7kIhcGlMD%j}olc$&*P`5sT(?0El6_Ns3)?=kov Wc09w$v{4!8T?S8AKbLh*2~7YDE0!<- literal 0 HcmV?d00001 diff --git a/data/bplay.png b/data/bplay.png new file mode 100644 index 0000000000000000000000000000000000000000..91644c6ef1f25778ff61eef4cf935a726d476af1 GIT binary patch literal 425 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fY)RhkEMm@^hBIS8vkopMUlG+U2p=Z*J0=en4rH*cY~d_jkn%4&2(dcZ$OOU2GM{ zB=`?zSG?Ci3?ShCIxnp|bBzuL-|crv1&K%l73W=M^t*=$O6euJir>ZDt*_RSerTou57y Qzz}5cboFyt=akR{08|{O!~g&Q literal 0 HcmV?d00001 diff --git a/data/bstop.png b/data/bstop.png new file mode 100644 index 0000000000000000000000000000000000000000..a7be66d288f0a898cef29f5536841a9565d37bf7 GIT binary patch literal 401 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fY)RhkE!bz%@Q&+imYNj25oH6n<(<3wjq@ z#HiJ0z{~2Jl_!{a>SmgfqLYx*hsk#$o>hL?c>Kd0<^bk;2mXj2yJxQ=J`1`Za5++Z zZr!T9w7j%+tL7D#34XlsVu#xg<`|bFp;zxOT=kt-@8esg{RecHKAAr$sOW)MANw)g zOEYU~PK3DpiB_8S`OEv;Ho*y3XQa!0W^brkc}w?^=hafyIkT1}>K`g)dNIB4+O;m_ zKDh&Da?Cf*v`i3fUD5E`fM+-7;nKAY>vC`3J@W8Xm+baM;!AE!)w|Wwwe9TgnmZR> q91p*wnSLPL#Px#32;bRa{vGeh5!Hxh5_cX1T+8u00(qQO+^RT0R;pj4gVHSU;qFB0%A)?L;wJ) zjUzGu03IDlL_t(|+U=Zod=ypJ$GU`G5Wq{{`S*0R9EwUjY6E;9mg#!jJI(7XSeP!Tk6CJOF}q*d;F@G?dK$<-b$- zzXO21OM<=olC`^N(yARx@DHn}V!qOEfx;y2ZucbaFhDTKJG-anZE`3Wo_ z#Jk!&7u0cU5|GuX?8Kd0g22GEs!jEi%2;1+qAkw2Eiirs6yj)xi+Sla5Z{i zf_(K^AQl1r#q6Y4x|&_JQ~)W@Tk18OI7|pcBpklm@~-Pr*@8vHf#aRl>NWd4LC=ba z)9RF}YvaVS$wf?;`$dC%9jPAcyLulg0i>vbNW;hJ_&+VF5+eaSv zL?a<0;lx4YfRU%GX2gej1w_ON_mmT_3A(8;J^deu3bFa(PwBpt#ERV~mMTSr z0YT-`N<|e9?pqcPBN7Q`$3B@(8JP@feQ*1 z#}+S|$}y)+RLM-?FJ{0J*|%%V#1fIFq%GIwJ(@@61Ixxy5+@GCz72CE1(h61ytHw8 z@7vb&FZ-k;ujGZ2S&=!;8>UWrv*zM%4JKzfWi;}r@E?QxI488au78Rk>GO`-x-TK& zSlPTni;i3Qiva+k#}ctl+;AdHqi51nPSQAwuld?3cSa*2)oL$uts0r+TX|yi$t97c z7k=CIzLpO@+W4V|o^JHU{gZlLTQ)cG@F>^3h@B$aK*rB=a{xXs%)4YiY2w83wjdWa3e6?XgugR~ASqa@g ze5lD|&vt$J>voF=ZJTsrV|wZZSFSfVGkaIYx5=Y-by(SUV)IWPYxQh{_3g6ebb5D6 zn`J*SP_2ZVl`kM7KRbLGUF%9CER>v|jh}lK;+V`Nb2RZmoYk4hs|=b?M-EqQxi)! zD35@IGrG+8gDS@yDB=BO;t?Bw1P!N)3;^LKp<4x8fGU_AVEh^_J%i-CpII5x=dl|Q zpRN*FC9!v#r$3mHn28RC-F~?0v=;jZoLrE&WA?^wD;}CsV|3)_`tWPMsPT1^Z+pf5 zyg4!c#CJPC{-Q~Z@@5zf@`$(&omRi--rTksV)V6xTg1f5T@po+qJn5elD%>`>wQWcvAfQ8<+r3`H!C2DO$$KdZb z@14-6A(EjyW43qeeSCsDM@K;?Z)b+f>b~I@B7W*vW7MWu`}Lx>0ph0f5FOXd>9pckSFhNL38;XEih_({{jDHdhZ1z&4@53ogmrf| znHE3){dn%O*D5*J6I`pzF#Z zpyL@l;?zgd_2>vVYDEuyd+^5GVcScm^!@&zUqD3#fK6T3r>6Fn^@MAZJ3ajCsExy7 z28}3Dp-=a$98~nEYknT^+z%`2?ne#jylmru9MWOg#t!>^8sKKV^W>|GmcMtOVHC$K z*gL!bpdlkiEP7|ZIQ)<5si;fGEwI{Hqztein7-D#QY4Qg;cOjm%dEt&7oeb_H?JA{ zL+WemB^e#P0IB*94HXRy4HXp?txz5qOh{r?)hB1oeH#fKZT_D9^W-P8{&OZW9S|?9 z9b(2Ac8gjB0QiF$4GsPG(SlDy$DyY7`)ZnDl=?iU`byzA3R~@=TK#eCX&napubL$rILh{rb6{&3nG|aofJH_j&cB zmwUeO*)y|V+0{2=fp8>J5z$TPLf-%f*!RTj8TFzO5#mm4c|*+75!|ciT6EGcR|&#V z0nIe&O2%3zIkTpIYgpv*oy!efAEANSbjA9kA>j0RHtgy9Y4br{W2UU!c=7}pP6C6B!GSeoTJ z^y2UW1_xwhccQ#y%5W5P#Bm*?KG`N3)VCiRB97dQc{5v&=rw$H+4~@4|%}4<5XD@#4XQ2RANUCJ;I6wvFns>J8rx zhs6Us1leq;J2ECB3LSa+^qe@;WrQLBaPtAWVYI*BxIGyK{q=ip9=28TOJA{MFQFxF zcq?X5N|M4-eBqoL{#Ldi;&Ik z>&2x4h8-}Bw0=kBCgb9wf~l{dA?g>FO?qR?@8sbk4>ulsMnmtqVQ8~$efEvtws_0( zEwR5X*!Ru0KEt1Hc%uny0EXNp%jb0T#5;oCY(S7qQnN7~tk_x&PyXR&gbbgn0n!H} zf4yF@$gh~nC@D!_O&jP+Cl42HyvV5V)Xgh<#l;QUReAakAB=82sqxhNrriC_!=qoE z+oQsyKEJKsx_Us{+YnHZ@#4aTEA{j@@25@`RXvCU8ajUnj*nli58>MXD^mgEZvk;= zha-<xG8UL+SGe`{e{A2vT+iDlL#VklE+pS2{UT0eW&@_ z^*{A{5>Sy%CgjeWbYg@7K>%V6*c{n(Ou1`qxv64ffM7l=K3JvXhX+g^2Aq{3AL_q0 z78h>Zcu~-At?<)`=huJVa&hD-BqL=M6zu56v><0$CeC=E+Uyle-})bP6ufwF;aa}< zP(OTHkU7***m28%E`U=eD%goKRH}D z5DEx!?46R(`Gp_ue{k8Hz7dgV$arz%S|6Jg{;#Y6{&%*C-I*l0QBnuCEjWOV|h=lj%E_&cP69NzJHH*)G zCj^0~0ozKp>5J1y#D)Wb7^VVD+foJhk_q1J!M~@I%bAwX*2jSuo-oBQ6-UI;;(l%P8_1hQCg^NT+`T@xJzA71jd4%KslT_WsuJklA5 zH4$G-^8yl%23__#v=I4c&Q3gx*X+J9xP4~t?SfzqZi3}6=R4GV0gr%}#Z_OLRkwo4 z0&nukvoS)5)o^jXRqZO~tW+_nfQS@bA>&z3i2T*l8)lf@R}tFXSz_pBQ6Lzkiz|Vh z1%{TpiLKRRJPtGif?t1@kEuakM<<~~>$av66bl1HB&1Hy9xh2pjGjJ2zF-bas8puG z#8oA9bX#MU5EGc+BnHD^D8hO6Jl6kBD?G|g`6iSD>G)a@8J-e^H!~#S)LW&Q<6_w_ z|J3;9c<~u-z1IhuYAZoQsRHteYmXw>2)8fXHBLQ z2LozU&S-!+B=G;8y+F^!XK4RpcbtFgbkN{PDWHoNQviElrL(bQ`@V>#F?44wz#2;# zvu%mOUC-I3=Zkh;01>G{gES{WHe8SsWAXVz!6v=7I0!Lo1(QC19H549Kt(5;bIlsp zF;b$)2V?PSK{>Eo)Q9}@(nUNoWSYRnXKd*~4IO#cxl_o7{O`UgwTTbGWPnycTI13V z|C2fbyCWX%WX4i*PP)7^@aqOga&IYFHk?>M3@ZkdavQ240ObB^`Z5h}j6RYrSy!~H za6m5EEhypVKyI8ZJBx-+Mu`S@gcA~n1wdpOS2aDPf#>4`O# z;)hzuJvwL0J=MscDm=G?kl#4Gt&^?Ly2Bp#daR1|y%SMBSh#EJT) zNw{E!s5St+K@$GHGz{3)NXLN~*F`|#k& zP5Hfl`d}eLFM#HSo4vx|(8;SVl|(R5SCaf5Ktw_#gCkXN7QGh`5D|rPpp!u&yVy?( zImk&tb6v7OkwM2R$m7>kE94#gDFgw`C zang~E;)*DTRMZSGIUtt~eTg$SD9Nq(^EhUv-*sZuq0aI~G5<7k0ktC7%EpYsFbVLI z&1ud@`pc-!=j4VoO>qd3mtQ@6`Cb47CErtmH-yV7GCuochbv`&zw?8$Gjhno7bI~) z9?Bz|^Q4i&DUOlAE_ShxLnLtu7gima7TN|CN)$(#oB)~}deRYTiBGppp7~537&8N| zq&3IiO5AW%KS%-z>}Nmw*vDS>v5)=iCxHVTrKUwMZltFkRs* z>M}XAzp5|vr==1WpRw^ku|Z(W45cuTp=5+P8R7HfS_~)=dR0?2U-6X4ptwVR8fW=J zXOWEwFUuO>VhwMzA)GwEex4lbx$^n0x;3qsa)NqVzSmT{$TVueBnEgeh+$-2?(eF{ zP^~YO@-ZM6rI-NlCg*$XCfm~2;0ZMQ#Ag5k7i)NnUoVdb+D^;T2-M7ncS`X9prdoGhN{aUGpZEh+e99u*s2WF!^{kb?b!3m0b?%;%TF zgD5xAR(Wj0{Qg-^Fhj8-1;DiK>fYefGSV})wVoH}L8vMi_F&_mHC?XRc+tbpnX8kU z=DX}s_7_i?oQ{U3@5$G^JEZD=l8^`#*Z6Be0uZD!m=RpKs1IOc*%D(0#ZZwN+?DU; zhsidRLq)~_-LmT%n?tQYx}#R>OGr%H?Sbd=c@Qg%YWc+4N&|7`yA&T@nN)ZxppwSE z;0r#Kc9gz^q*VTzATv3;7d6O?>j17Vq!8dS}64P1|eD?5g0m2k)@?k~`yOsjXH_FAfz@P*@N; zCiimT_3HOu#spQcYxED9T)6O%%3!{@L>{c*Y;l#!+D+I2eha;PDB}8w5#_^xKn;l! zjk?0MbY=6OzQe~nTh&DodjUHGd`z&7&dkq_+KoozysRmTf_Y%nm7Zb9pYmWeC#(vK zVp=evnM*tluqxk3ks~iX)X$ozynJ4HgQ|uN9(2114|14fE;mt&Yb>By0Qi_nPUsD% zN$&MT*UOx$wgYQVpagg@vJf6jBh6NQTnyFX_KcrQ3KR0*a7;+~yzz%PE;B!8ca8Rh zs>|ZR)_l(#~mK6d;=IU0+=4yy>!MY=Z%|<&<&bVIAGrVl6X`;TT@C0ADTc za(M+A9UnfxZj$*4H(tDNx1alXc=rFw007XRuidlKYvYK(i;tzm6r7dyvLtHiTMzDe ze?_wnV#NY>nzQXUR=(0}t!K^t7Rk2m=&^>0AOBbbN4Tp6 zu5b^LIxROc{f>^K5b)t;DPI;eQU!4FlVeQNGc#T}-g8sTi0p8*nU3u6v<3poJvX^Kjw5zD~)pt0NCryZi3&cM`dR^#WyU z{PqHzC-#wM!%TCyj=^LX{?HEQT=QkacRyV7U90V{9e+Kub8eUHce39-+vPyi`r$Dz zzWvc%V3 zcsNy};WI!$tp42L7kvPk{CsZUu9Y;UBwoCnqBl#!b4i7Lk{&P9+^h`ohu{yS*V;XR zFNjBmV`9nCV%hLG5MH^w=&a@&ds-lsemq7mzRO!!ZguRG3RUpp#l=JhaQf;2kSTZu z6N%uD6nk`;*@>AfU_5PT#t+CzwJMD=SB(^l3S1L0J*6~X@gxf{wm#G{Gv{6R()7lS z&83mQ(Vg!K3Xj70sI2mKMmIb^bhy zd4o?mZ0=VR-TAB1>%Y7u4M@DrtPlxoq%>b{%G=yh^ks5)6VKk{N>s#y4;c^fjO2CtvxvQg z0-=&hJTvIcn~Y^U9y8NN>nG=}m{!dlbG$A0G6@;>NO!g{gCnnhMKS^kKjJC6Qdz^q zD5jMBX-p43lp7i!uLi`@lI6(AxDz%FefE`Eefrg^hind5UF_mJ`q7Cu>C4xA%N!Om zk6BD&IK6n4cNor(9Kd6C%}ZqKmY>Z(J!W2=eru3$a)F_=l$FWl)N` zNXn4DYBkY^jHbVJ4kpoy9RK!LStkX)bq;S*XWX09nsuNWK73~8#zPwWSkKQaU^equ z$O^V`m~3kSnGY`l4L<&~^MV5(4z9i#QBO`m!a)QP?4}I|l5V{I8Hxi7sTUoZv&o8q03qs)~3l-#|$kzbA({MKFfP||!(4%$V@_}A!)UjF)bn|?X) zmTv6*@{h@yF%R!m(fvC~;@~W=W$uu>A(?{knJJMlasuJc3@K(JQbphs-w3AIeFD0x zjNAA=i&v6j*)ea`uoo%}ef9g!(|h#q+L?!=?=N{PH&BU+Tt|(_yScqy>&YJs9o=(o zv+1jQ_Ppo7R~(hc^CHIpvK^H2J6v;!(D8yIwz5+6{xvtnP$Hv+Y!jjLG`|yL>;V{9 z$dz%k0x*MtxbWg-zFS|*Oy}e(qZ>~265A;C)q&k7zc;=6jPBFAj(@WeTTaDxuG#nY zFUx+%5!l2@yvQ7-JtrWO64k-B>5xvg++KT;C@X=cTI;Bai~+$#kp3iugBuxU8b!ZN zRw1n}@Czd?gPF_;^F1?_VVwVY%QvIO@-<@_%lMo}^Yi z>o05G1k53dii-*NfH$gvM)%*|Y!vs`K^>P6m)| z>8%cA04hW9nr6?#Lh}u)tkm`{^IS$?+=)mmv8nf3Ye&5{-+#_Bd-meye#Wo+ z0k5E;tB<%Av(Zu)LzZ43j(rH0v{s`5>+o9DJpz;P0zUuB5OZ1Bki2NB*=7)ZRw6XO zO^PcmUQmKmv0R#p2HL&)NdIA;83bQJIV;!-#Cf~SoU@J| zzT3On4A8CE&t9eJv*>Hz8sZqIZIm`vzbA1zWLrreGD|3HEy1&^k!-oSu-)F(w*jH+ zov=-ADz*qsWupa2pvxyYW!pT`xb7p7leWcWO2}qedQectU&(;{PSHNQ8)&v6t2o;h zvVMYRu+JJ(__v;vk=You<7NQJ(1kgFu@NjdOtNnjYF|p1VF3{6mdr*A0L|v)&WG$Z zr-oMoRonm+Y@*D~(nEGj^4Ef#wy8-dbM$;h_8$U(o(}-cwvUo#lWRfe0zN`7;C)4QOtiXSbgje{9_nk|6gH5)500006VoOIv00000 z008+zyMF)x010qNS#tmY3ljhU3ljkVnw%H_000McNliru)B_9$6ES^rX50V(03CEi zSad^gZEa<4bO1wgWnpw>WFU8GbZ8({Xk{QrNlj4iWF>9@00FZ}L_t(|+U=ITZo)7W zMvqAVHELA`s>0gWqR#*`&(g7iC+XC+570GIhF0Y_ki=cCCF7D(l0X^qNmsVx;htQ7 z*9p|BRjbx%r7kJI`sbIc97b8A+VkuzFfN1w8qWGqj!Ix$027`yH+#S3DGlR7cz|z( zSvQsP? zWipxQUawckGkyWj*j==v>2%6qFn9-EfGv;$i4`f3 z*;E1Z*Un2Vpje<*0=BYDT-h=G2A5f_ZSI$?HJ$_}PbNv01D2cr>e{`P&?QB d#i)kK(>JL1R>e3wvbF#K002ovPDHLkV1lpv@P+^Y literal 0 HcmV?d00001 diff --git a/data/fr2.png b/data/fr2.png new file mode 100644 index 0000000000000000000000000000000000000000..0b14911cfbbf25389f5ec4fb19322d6223852e2b GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^%0L{&!3HFazPt|rQfx`y?k+$Y2!1;6t_M<_1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPWGY`9%r0GVhWT232iEBiObAE1aYF-J0b5UwyNotBh zd1gt5LP$ocg1e`0!21-{JfOlBPZ!6Kid%2bDRMalinw0<>(YJj(UQ5dj0KM-ZP2he z?LIkzH~X;Wbm?m^%9C&Ix)pLeEBx*1$8$b^ws5<;a98N`S0Qs(zb@Jx-v27{Z0h^4 gzkvoMg8NmBJ9qPMd9;G#JJ3B0p00i_>zopr0Q|6As{jB1 literal 0 HcmV?d00001 diff --git a/data/fr3.png b/data/fr3.png new file mode 100644 index 0000000000000000000000000000000000000000..8e524fd1cf7341745987187aeb7883ae3e807873 GIT binary patch literal 657 zcmV;C0&e|@P)500006VoOIv00000 z008+zyMF)x010qNS#tmY3ljhU3ljkVnw%H_000McNliru)B_9$7ZoKOM+pD`03CEi zSad^gZEa<4bO1wgWnpw>WFU8GbZ8({Xk{QrNlj4iWF>9@00H$$L_t(|+U=LmPQpMC zhreyhA6GF59(pjwqX!cbUqVm54`(l4IPwTQj7J~Bga}?tsKx^8WfnJuLQAXBq?1f2 zOS|)Rc6NS?Vz(*r0H^^PI0m}FqcP_DMx_8AfHzo;0NYZ8+z0x{}q^B5WfmzgL&e33H&f~dZI>0&51D^W*zA4M{bm~9~ zu??I7SHQj2dM!Kqnx9iTJO``>JjZc-Ivfr!XR{f-UXLh>&{`L6-C35(mo0k$v?NPi z;10NzS_;b0kt|)+my9%=vv6DLs3X@cfvw34sH}w=0>jh9YVnv#_y%+Au-R}O4&_j@cb z7Q|01)6RMg_5iWj!TB?`Oe|gCv;mbBMitnF$#aY6WWsZP+ZIQa0pmWK1WTUgRMyr~ r1SSoNj37S(Q)E7sJe5^e*}t_f%l937G-3X^00000NkvXXu0mjf>(>Mx literal 0 HcmV?d00001 diff --git a/data/fr4.png b/data/fr4.png new file mode 100644 index 0000000000000000000000000000000000000000..fcbb28857b05daaa818ef3240f2f043483657fcb GIT binary patch literal 375 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 literal 0 HcmV?d00001 diff --git a/data/fr7.png b/data/fr7.png new file mode 100644 index 0000000000000000000000000000000000000000..10476aa5ad185976928d26854198f4943d2a5d59 GIT binary patch literal 1184 zcmV;R1Yi4!P)WFU8GbZ8({Xk{QrNlj4iWF>9@00aa{L_t(|+U=V=Z&OJW zfWJu`NHF4|)eQ~ELEx}TM?;%bOM@Tgp;<;L|APz$CkzDVfZuDi+Qm4I0odBwVsmqo_4V~& zbw?H!7MPitp;D;;P_Nf%Hk%1>ANUX0F)+LnF!Y>2G7|__Ja_{e2TTI@Yqi>M7J?w@ z#lY|kcmljJ`p#%q#0{Cff&y+792<;_Pr}tGiXLrmZwD`s(>qL0Pm?6c3h=i9;jICo zEj|(Zd13|aQyYzj4w7FQjfPh{DXq1)9QN$&ENg3Pl*{Gd4RU&gcDv2u;vyRx8-6l> zK0#1Q;qmq(CqDbrYl^vAtf=4LGBUGzZ?-{NTBaC{C06Z*s)*ur}7osS-6J`yC z%^F?+|C?Nboj!I3B$iTt8g>fKA&i?m!XB`nB*|a(di_cq$5bj6=I7^wg)`(4k|fzN zw(5w4(yjoZ=S&}US`ZRXAWQkr1S(PnY0JI5cvb!S`fNg7yFq3d<~(fL8-9%u-(1RegpTRI9S4S@)*7@77WEL9e^}|a`q&Wx&aQx<3{08dND%rx zcN7X!?B5cE4;-v8wjCIXT7A^AgUdq*QW?F1oJLNW(O(uiW#S0w5yl31gi!%OmZ({e z&=oKgS&yLI4xUI645o<{`c)`R3IHa}vnTjk!>9rXUp@~X4GcYsuTav1MsV8MK^hoB z&Eg@ALAIL3G!W<_MtYiSLKSm%5PVfJ>!MtKoWFU8GbZ8({Xk{QrNlj4iWF>9@00Q|*L_t(|+SQl4ZWBQi zhQD)mgHebRke~_zQIIEyM3*iNQhHt>&p?xhpidd`3JGlzdWz7*4HBXW2vB^9jCXeq z#m?H}jkCVwVi;?*J2Pize*bgMnSX@oi*U2WW?fVO^-q}-Q1jIl<1zwZ1jN2ZzV9x9 zIv@j5Uo*hPfq?=GzUU*FR z3ZRi^a22qfogF(oJhXX~?d|OX>>Ceu6(gzKhb0obUTU%RvJ~^S;YUQ9jm|_m~?}IsWpq)-9^xen6 zauFxxVCuKc87|Fm7^ap3Rz;9}V>FKg@$Vv#r77)pn|i&DsA6U~=P=cNG#1SFgF_W{ z`EHvHC4eHBV?Z@vR4%0=k%4<(nTe|nM8Y&-)8zbxAmfNmn~6(&ROTuxePPpOwjpC3 zXDK6AAMTgR??b-DGdz6$*hFBpIu+YkmhIZ7L zpU~w)xri8mbvS>9=VN9@6h(YIJ|;;L(k#na3^YPn$P|45-ENmgqfuZ>3egN$ToSD* zz~0^-D=RCkt*v<`9a%QHKb@bS&*X=VMuXGS)1rCd1$0^vSV+8O;H4L>^A^sZfVaSF zk7-!~;ameA0Z+ZMeg-`8DkdI^iQBn~m}l<-_yK$cz5w5V-*IW%JHU6}*9`UG9o?CV r`%)A5>9KTxG+Z?LmoIn!&2{-N5-ROjJofpn00000NkvXXu0mjf#{P?L literal 0 HcmV?d00001 diff --git a/data/icon.edc b/data/icon.edc new file mode 100644 index 0000000..0a3ea3d --- /dev/null +++ b/data/icon.edc @@ -0,0 +1,14 @@ +collections { + images.image: "e_logo.png" COMP; + group { name: "icon"; + min: 20 10; + parts { + part { name: "icon"; type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "e_logo.png"; + } + } + } + } +} diff --git a/data/knob.png b/data/knob.png new file mode 100644 index 0000000000000000000000000000000000000000..f39f738a5c016744b2bc46dc69709aa8f4a37138 GIT binary patch literal 1076 zcmV-41k3x0P)WFU8GbZ8({Xk{QrNlj4iWF>9@00WpwL_t(|+SQd$Z`4K@ z#(y5qV4H&1*^pI9QlJ8H>8VE~q#XJYsCwkH+awZUdhr5CFnM0-=ZS=Pl59 z)c(6&7YaT?9v&VZK1|c}u@K_GId{t#Ls1lGd7eKX4u?;lJ$v>Xs5~sN@PZxQnv0eI z)ba80_q)5hPqHlg`s&rITTv7VDWwR*FjGo>m8R*p+uPgsPESvN^B#T>vhWged2({{ zWhhazV!2VNp)m%nHA*P}thIz;NYgZwWyx$dLu-vO24l=BAI>=ziv^yz2Yd!x+4MjZ zMe#~0bsNArht_%}V68=K&2&0ld9xI%s*18K8zAzy0!X=81bLqSB&EDv*EPl%q9{TL zLEE-iYca+!pU;_2r_5%vl~7rhXsxSFKDp7f+Tn2cG)a>0thFRbf>Meg2^D9)OGy| zcm<4rKY_R51)Wo!o}T{N@An_HZ97;On9t|$g=a~AetzzZF=xOVPyRdb7w|5;r0>ho zX!MJe@^064`+hWjX1(?i_gMEgk|d{PQ(X1Q#_sAn}!W6Sxh0=__=wYytkh1qvYd0xy9- zfWLtWVB`hkukpj9@Ow3&y_GjE5g2>YH^5uJR{@Q@U>>xd)cAL|Ca|hde|O=}3U6@% u%)M|8v>zRro-6`lk7#WYHlFO#k@+7GS4X=<>&kwGnTJDHY|?}N??55h64!_l=ltB<)VvY~=c3falGGH1 z^30M9g^-L?1$R&1fcGh?c|e8wo-U3d6}OU85)yu#H)vtxW@ctS{NLF5^2Z)E9v&Ya oXPKU=ge%O-cbR*f_e!ubL|C)%pX2*r4b;lu>FVdQ&MBb@02sA3TmS$7 literal 0 HcmV?d00001 diff --git a/data/pnl.png b/data/pnl.png new file mode 100644 index 0000000000000000000000000000000000000000..28f1915de5667a675aa82128baf91c400eaddce4 GIT binary patch literal 705 zcmV;y0zUnTP)WFU8GbZ8({Xk{QrNlj4iWF>9@00JdRL_t(|+Ra$oj)gD? zWD@`XhdmqiWlbt_8CpGVAGNj>m{7HbZOh>k==5l1up)zF9uBSbLd6Gh8SV+6ye z#^onwV3>utjS^dgAU3FqvO>iP-bVyFDe!87{hne%EeZzcm|&;K7n|PL_%>Q3sj!NAJ|C;R>m+ zEa=uqMntQ+(5iuo`@3#AlHv=A*%W{%u*yG12X=oZ>I+_R#a*W(g$78X8}M9lX1}sN z4@s&hQ~GT&Ivvu&uriVz2r|8fX1$>_iKe<+_`kj3htTuL4Xv`HR#!AE?5epT9KG(C zx>|WE1$SwFMaSYbCLp-KBTQOw!Kntyi8u6tEjhkZm{R175dfj@Y=oxd_|AJmI(5+j zm=1YXC)9evo%oZMz$6|(SS?`OEeh{Pt=APJ=Kim>7Hi2s9;S2091>A>Jr9EIK-x1f zO!zfF(7k-hG@-hW~+ErJMgqCrXpF1 n5rh4T|0zFEDV#RK-#W-IFWg!GZA;8Z00000NkvXXu0mjfi{mGr literal 0 HcmV?d00001 diff --git a/data/sl.png b/data/sl.png new file mode 100644 index 0000000000000000000000000000000000000000..119d11f91bcdb7d41ad7a46dca4c9b6e0aaf24f3 GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^oIotV!3HFcc!W9wDYhhUcNZWH1V5d3*8?fe0*}aI z1_o|n5N2eUHAey{$X?><>&kwGnTJD1X_dbhGf+sj#5JPCIX^cyHLrxhxhOTUBsE2$ zJhLQ2AtWPJ!QIn0;C+f}9#EmHr;B4q#jUrK4stRm@GuJ({y%FKT*IN1E5iO^-pN2O z&455YDY+j(6IE8qOmUmRy0gkkvD=1ocSWp?5(9%Rd)ch&-ZKmbIK>|uWEwL84P@|i L^>bP0l+XkKD1JLW literal 0 HcmV?d00001 diff --git a/data/theme.edc b/data/theme.edc new file mode 100644 index 0000000..63e732d --- /dev/null +++ b/data/theme.edc @@ -0,0 +1,1667 @@ +images { + image: "tiles.png" COMP; + image: "window_inner_shadow.png" LOSSY 70; +/* image: "e_logo.png" COMP;*/ + + image: "h_slider.png" COMP; +/************/ + image: "video_frame_left.png" COMP; + image: "video_frame_right.png" COMP; + image: "video_frame_top.png" COMP; + image: "video_frame_bottom.png" COMP; + + image: "knob.png" COMP; + + image: "fr1.png" COMP; + image: "fr2.png" COMP; + image: "fr3.png" COMP; + image: "fr4.png" COMP; + image: "fr5.png" COMP; + image: "fr6.png" COMP; + image: "fr7.png" COMP; + image: "sl.png" COMP; + image: "orb.png" COMP; + image: "whb.png" COMP; + image: "bpause.png" COMP; + image: "bplay.png" COMP; + image: "bstop.png" COMP; + image: "pnl.png" COMP; +} + +collections { + group { + name: "background"; + parts { + part { + name: "bg"; + mouse_events: 0; + description { + state: "default" 0.0; + color_class: "background"; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + relative: 1.0 1.0; + offset: -1 -1; + } + fill { + smooth: 0; + origin { + relative: 0.0 0.0; + offset: 0 0; + } + size { + relative: 0.0 0.0; + offset: 128 128; + } + } + image { + normal: "tiles.png"; + } + } + } +/* + part { + name: "logo"; + mouse_events: 0; + description { + state: "default" 0.0; + min: 120 140; + rel1 { + relative: 0.0 0.0; + offset: 48 48; + } + rel2 { + relative: 0.0 0.0; + offset: 140 140; + } + image { + normal: "e_logo.png"; + } + } + } + */ + part { + name: "shadow"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + relative: 1.0 1.0; + offset: -1 -1; + } + image { + normal: "window_inner_shadow.png"; + } + } + } + } + } +#if 0 + group { + name: "video_controller"; + parts { + // need swallow parts: + // "video_swallow" + // + // need txt parts: + // "video_speed_txt" + // "video_progress_txt" + // + // need dragables: + // "video_progress" horizontal + // "video_speed" vertical + part { + name: "video_swallow"; + mouse_events: 0; + type: SWALLOW; + clip_to: "vclip"; + description { + state: "default" 0.0; + rel1 { + to: "fr_c1"; + relative: 0.0 0.0; + offset: 20 20; + } + rel2 { + to: "fr_c4"; + relative: 0.0 0.0; + offset: 14 14; + } + } + } + part { + name: "vclip"; + mouse_events: 0; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "fr_c1"; + relative: 0.0 0.0; + offset: 20 20; + } + rel2 { + to: "fr_c4"; + relative: 0.0 0.0; + offset: 14 14; + } + color: 255 255 255 255; + } + description { + state: "faded" 0.0; + rel1 { + to: "fr_c1"; + relative: 0.0 0.0; + offset: 20 20; + } + rel2 { + to: "fr_c4"; + relative: 0.0 0.0; + offset: 14 14; + } + color: 255 255 255 180; + } + description { + state: "dim" 0.0; + rel1 { + to: "fr_c1"; + relative: 0.0 0.0; + offset: 20 20; + } + rel2 { + to: "fr_c4"; + relative: 0.0 0.0; + offset: 14 14; + } + color: 255 255 255 80; + } + } + part { + name: "fr_c1"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + relative: 0.0 0.0; + offset: 34 34; + } + image { + normal: "fr1.png"; + } + } + } + part { + name: "fr_c2"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 1.0 0.0; + offset: -35 0; + } + rel2 { + relative: 1.0 0.0; + offset: -1 34; + } + image { + normal: "fr6.png"; + } + } + } + part { + name: "fr_c3"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 1.0; + offset: 0 -35; + } + rel2 { + relative: 0.0 1.0; + offset: 34 -1; + } + image { + normal: "fr3.png"; + } + } + } + part { + name: "fr_c4"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 1.0 1.0; + offset: -35 -35; + } + rel2 { + relative: 1.0 1.0; + offset: 9 9; + } + image { + normal: "fr5.png"; + } + } + } + part { + name: "fr_s1"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 1.0; + offset: 0 0; + to: "fr_c1"; + } + rel2 { + relative: 1.0 0.0; + offset: -1 -1; + to: "fr_c3"; + } + image { + normal: "fr2.png"; + } + } + } + part { + name: "fr_s2"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 1.0 0.0; + offset: 0 0; + to: "fr_c3"; + } + rel2 { + relative: 0.0 1.0; + offset: -1 -11; + to: "fr_c4"; + } + image { + normal: "fr4.png"; + } + } + } + part { + name: "fr_s3"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 1.0; + offset: 0 0; + to: "fr_c2"; + } + rel2 { + relative: 1.0 0.0; + offset: -11 -1; + to: "fr_c4"; + } + image { + normal: "fr2.png"; + } + } + } + part { + name: "fr_t"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 1.0 0.0; + offset: 0 0; + to: "fr_c1"; + } + rel2 { + relative: 0.0 1.0; + offset: -1 -1; + to: "fr_c2"; + } + image { + border: 50 50 0 0; + normal: "fr7.png"; + } + } + } + part { + name: "panel_bg"; + mouse_events: 0; + clip_to: "panel_clip"; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + to: "panel_clip"; + } + rel2 { + relative: 1.0 1.0; + offset: -1 -1; + to: "panel_clip"; + } + image { + normal: "pnl.png"; + } + fill { + smooth: 1; + origin { + relative: 0.0 0.0; + offset: 0 0; + } + size { + relative: 0.0 1.0; + offset: 32 0; + } + } + } + } + part { + name: "prog_container"; + mouse_events: 0; + clip_to: "panel_clip"; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 0.0; + offset: 4 4; + to: "panel_clip"; + } + rel2 { + relative: 1.0 0.0; + offset: -5 9; + to: "panel_clip"; + } + image { + border: 2 2 2 2; + normal: "whb.png"; + } + } + } + part { + name: "prog_done"; + mouse_events: 0; + clip_to: "panel_clip"; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + to: "prog_container"; + } + rel2 { + relative: 0.5 1.0; + offset: 0 -1; + to_x: "video_progress"; + to_y: "prog_container"; + } + image { + border: 2 2 2 2; + normal: "orb.png"; + } + } + } + part { + name: "video_progress"; + type: RECT; + clip_to: "panel_clip"; + mouse_events: 1; + dragable { + x: 1 1 0; + y: 0 0 0; + confine: "prog_container"; + } + description { + state: "default" 0.0; + min: 10 5; + align: 0.5 0.5; + rel1 { + to: "prog_container"; + relative: 0.5 0.5; + offset: 0 0; + } + rel2 { + to: "prog_container"; + relative: 0.5 0.5; + offset: 0 0; + } + color: 0 255 0 50; + } + } + part { + name: "video_progress_img"; + mouse_events: 0; + clip_to: "panel_clip"; + description { + state: "default" 0.0; + min: 9 16; + align: 0.5 1.0; + fixed: 1 1; + rel1 { + relative: 0.5 0.0; + offset: 0 0; + to_x: "video_progress"; + to_y: "prog_container"; + } + rel2 { + relative: 0.5 0.0; + offset: 0 0; + to_x: "video_progress"; + to_y: "prog_container"; + } + image { + normal: "sl.png"; + } + } + } + part { + name: "b_stop"; + mouse_events: 0; + clip_to: "panel_clip"; + description { + state: "default" 0.0; + min: 22 22; + max: 22 22; + align: 0.0 0.0; + rel1 { + relative: 1.0 1.0; + offset: -5 -5; + to: "panel_clip"; + } + rel2 { + relative: 1.0 1.0; + offset: -5 -5; + to: "panel_clip"; + } + image { + normal: "bstop.png"; + } + } + } + part { + name: "b_play"; + mouse_events: 0; + clip_to: "panel_clip"; + description { + state: "default" 0.0; + min: 22 22; + max: 22 22; + align: 0.0 1.0; + rel1 { + relative: 0.0 0.0; + offset: -1 0; + to: "b_stop"; + } + rel2 { + relative: 0.0 0.0; + offset: -1 0; + to: "b_stop"; + } + image { + normal: "bstop.png"; + } + } + description { + state: "play" 0.0; + min: 22 22; + max: 22 22; + align: 0.0 1.0; + rel1 { + relative: 0.0 0.0; + offset: -1 0; + to: "b_stop"; + } + rel2 { + relative: 0.0 0.0; + offset: -1 0; + to: "b_stop"; + } + image { + normal: "bplay.png"; + } + } + description { + state: "pause" 0.0; + min: 22 22; + max: 22 22; + align: 0.0 1.0; + rel1 { + relative: 0.0 0.0; + offset: -1 0; + to: "b_stop"; + } + rel2 { + relative: 0.0 0.0; + offset: -1 0; + to: "b_stop"; + } + image { + normal: "bpause.png"; + } + } + } + part { + name: "panel_clip"; + mouse_events: 0; + type: RECT; + clip_to: "vclip"; + description { + visible: 0; + state: "default" 0.0; + rel1 { + to: "panel"; + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + to: "panel"; + relative: 1.0 1.0; + offset: -1 -1; + } + color: 255 255 255 0; + } + description { + visible: 1; + state: "shown" 0.0; + rel1 { + to: "panel"; + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + to: "panel"; + relative: 1.0 1.0; + offset: -1 -1; + } + color: 255 255 255 255; + } + } + part { + name: "video_progress_txt"; + type: TEXT; + mouse_events: 0; + effect: OUTLINE; + description { + state: "default" 0.0; + rel1 { + to: "panel"; + relative: 0.0 1.0; + offset: 0 -10; + } + rel2 { + to: "panel"; + relative: 1.0 1.0; + offset: -1 -1; + } + color: 255 255 255 255; + color2: 0 0 0 255; + text { + text: "Video Progress"; + font: "Sans"; + size: 6; + align: 0.0 1.0; + }; + } + } + part { + name: "panel"; + mouse_events: 1; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "fr_c3"; + relative: 0.0 0.0; + offset: 20 -46; + } + rel2 { + to: "fr_c4"; + relative: 0.0 0.0; + offset: 14 14; + } + color: 0 0 0 0; + } + } + part { + name: "panel2"; + mouse_events: 1; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "fr_c1"; + relative: 0.0 0.0; + offset: 20 20; + } + rel2 { + to: "fr_c2"; + relative: 1.0 0.0; + offset: -1 -1; + to: "panel"; + } + color: 0 0 0 0; + } + } + part { + name: "video_resizer"; + mouse_events: 1; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "fr_c4"; + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + to: "fr_c4"; + relative: 1.0 1.0; + offset: -1 -1; + } + color: 0 0 0 0; + } + } + part { + name: "video_mover"; + mouse_events: 1; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "fr_t"; + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + to: "fr_t"; + relative: 1.0 1.0; + offset: -1 -1; + } + color: 0 0 0 0; + } + } + } + programs { + program { + name: "video_move_start"; + signal: "mouse,down,*"; + source: "video_mover"; + action: SIGNAL_EMIT "frame_move" "start"; + } + program { + name: "video_move_stop"; + signal: "mouse,up,*"; + source: "video_mover"; + action: SIGNAL_EMIT "frame_move" "stop"; + } + program { + name: "video_resize_start"; + signal: "mouse,down,*"; + source: "video_resizer"; + action: SIGNAL_EMIT "frame_resize" "start"; + } + program { + name: "video_resize_stop"; + signal: "mouse,up,*"; + source: "video_resizer"; + action: SIGNAL_EMIT "frame_resize" "stop"; + } + program { + name: "panel_show"; + signal: "mouse,in"; + source: "panel"; + action: STATE_SET "shown" 0.0; + transition: LINEAR 1.0; + target: "panel_clip"; + } + program { + name: "panel_hide"; + signal: "mouse,in"; + source: "panel2"; + action: STATE_SET "default" 0.0; + transition: LINEAR 1.0; + target: "panel_clip"; + } + } + } +#else + group { + name: "video_controller"; + parts { + // need swallow parts: + // "video_swallow" + // + // need txt parts: + // "video_speed_txt" + // "video_progress_txt" + // + // need dragables: + // "video_progress" horizontal + // "video_speed" vertical + part { + name: "video_swallow"; + mouse_events: 0; + type: SWALLOW; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 0.0; + offset: -8 23; + } + rel2 { + to: "video_frame_right"; + relative: 0.0 1.0; + offset: 7 -25; + } + } + } + part { + name: "video_frame_left"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + relative: 0.0 1.0; + offset: 32 -1; + } + image { + border: 0 0 33 33; + normal: "video_frame_left.png"; + } + } + } + part { + name: "video_frame_right"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 1.0 0.0; + offset: -32 0; + } + rel2 { + relative: 1.0 1.0; + offset: -1 -1; + } + image { + border: 0 0 33 33; + normal: "video_frame_right.png"; + } + } + } + part { + name: "video_frame_top"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 0.0; + offset: 0 0; + } + rel2 { + to: "video_frame_right"; + relative: 0.0 0.0; + offset: -1 31; + } + image { + normal: "video_frame_top.png"; + } + } + } + part { + name: "video_frame_bottom"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 1.0; + offset: 0 -32; + } + rel2 { + to: "video_frame_right"; + relative: 0.0 1.0; + offset: -1 -1; + } + image { + normal: "video_frame_bottom.png"; + } + } + } + part { + name: "video_speed_txt"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_bottom"; + relative: 0.0 0.0; + offset: 0 8; + } + rel2 { + to: "video_frame_bottom"; + relative: 1.0 1.0; + offset: -1 -13; + } + color: 0 0 0 255; + text { + text: "Video Speed"; + font: "Sans"; + size: 6; + align: 1.0 0.5; + }; + } + } + part { + name: "video_progress_confine"; + mouse_events: 0; + type: RECT; + description { + state: "default" 0.0; + fixed: 1 1; + min: 1 18; + align: 0.5 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 1.0; + offset: 0 -25; + } + rel2 { + to: "video_frame_right"; + relative: 0.0 1.0; + offset: -1 -25; + } + color: 0 0 0 0; + } + } + part { + name: "video_progress"; + type: RECT; + mouse_events: 1; + dragable { + x: 1 1 0; + y: 0 0 0; + confine: "video_progress_confine"; + } + description { + state: "default" 0.0; + fixed: 1 1; + min: 34 18; + rel1 { + to: "video_progress_confine"; + relative: 0.5 0.5; + offset: 0 0; + } + rel2 { + to: "video_progress_confine"; + relative: 0.5 0.5; + offset: 0 0; + } + color: 0 0 0 0; + } + } + part { + name: "video_progress_img"; + mouse_events: 0; + description { + state: "default" 0.0; + fixed: 1 1; + min: 42 26; + rel1 { + to: "video_progress"; + relative: 0.5 0.5; + offset: 0 0; + } + rel2 { + to: "video_progress"; + relative: 0.5 0.5; + offset: 0 0; + } + image { + normal: "h_slider.png"; + } + } + } + part { + name: "video_speed_confine"; + mouse_events: 0; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 0.0; + offset: 0 24; + } + rel2 { + to: "video_frame_left"; + relative: 1.0 1.0; + offset: 48 -49; + } + color: 0 0 0 0; + } + } + part { + name: "video_speed"; + mouse_events: 1; + dragable { + x: 0 0 0; + y: -1 1 0; + confine: "video_speed_confine"; + } + description { + state: "default" 0.0; + fixed: 1 1; + min: 24 24; + rel1 { + to: "video_speed_confine"; + relative: 0.5 0.5; + offset: 0 0; + } + rel2 { + to: "video_speed_confine"; + relative: 0.5 0.5; + offset: 0 0; + } + image { + normal: "knob.png"; + } + } + } + part { + name: "video_play"; + mouse_events: 1; + description { + state: "default" 0.0; + fixed: 1 1; + min: 24 24; + rel1 { + to: "video_frame_bottom"; + relative: 0.0 0.5; + offset: 0 0; + } + rel2 { + to: "video_frame_bottom"; + relative: 0.0 0.5; + offset: 0 0; + } + image { + normal: "knob.png"; + } + } + } + part { + name: "video_pause"; + mouse_events: 1; + description { + state: "default" 0.0; + fixed: 1 1; + min: 24 24; + rel1 { + to: "video_frame_bottom"; + relative: 0.5 0.5; + offset: 0 0; + } + rel2 { + to: "video_frame_bottom"; + relative: 0.5 0.5; + offset: 0 0; + } + image { + normal: "knob.png"; + } + } + } + part { + name: "video_stop"; + mouse_events: 1; + description { + state: "default" 0.0; + fixed: 1 1; + min: 24 24; + rel1 { + to: "video_frame_bottom"; + relative: 1.0 0.5; + offset: 0 0; + } + rel2 { + to: "video_frame_bottom"; + relative: 1.0 0.5; + offset: 0 0; + } + image { + normal: "knob.png"; + } + } + } + part { + name: "video_mover"; + mouse_events: 1; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_top"; + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + to: "video_frame_top"; + relative: 1.0 1.0; + offset: -1 -1; + } + color: 255 20 20 20; + } + } + part { + name: "video_resizer"; + mouse_events: 1; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_right"; + relative: 0.0 1.0; + offset: 0 -31; + } + rel2 { + to: "video_frame_right"; + relative: 1.0 1.0; + offset: -1 -1; + } + color: 20 20 255 20; + } + } + part { + name: "video_progress_txt"; + type: TEXT; + mouse_events: 0; + effect: OUTLINE; + description { + state: "default" 0.0; + align: 1.0 1.0; + fixed: 1 1; + rel1 { + relative: 1.0 1.0; + offset: -2 -2; + } + rel2 { + relative: 1.0 1.0; + offset: -2 -2; + } + color: 255 255 255 255; + color2: 0 0 0 255; + text { + text: "XX:XX:XX / XX:XX:XX"; + font: "Sans"; + size: 10; + align: 1.0 1.0; + min: 1 1; + }; + } + } + } + programs { + // emit signals: + // "video_control" "play" + // "video_control" "pause" + // "video_control" "stop" + // "drag" "video_progress" + // "drag" "video_speed" + // + // get signals: + // "video_state" "play" + // "video_state" "pause" + // "video_state" "stop" + program { + name: "video_play"; + signal: "mouse,down,1"; + source: "video_play"; + action: SIGNAL_EMIT "video_control" "play"; + } + program { + name: "video_pause"; + signal: "mouse,down,1"; + source: "video_pause"; + action: SIGNAL_EMIT "video_control" "pause"; + } + program { + name: "video_stop"; + signal: "mouse,down,1"; + source: "video_stop"; + action: SIGNAL_EMIT "video_control" "stop"; + } + program { + name: "video_move_start"; + signal: "mouse,down,*"; + source: "video_mover"; + action: SIGNAL_EMIT "frame_move" "start"; + } + program { + name: "video_move_stop"; + signal: "mouse,up,*"; + source: "video_mover"; + action: SIGNAL_EMIT "frame_move" "stop"; + } + program { + name: "video_resize_start"; + signal: "mouse,down,*"; + source: "video_resizer"; + action: SIGNAL_EMIT "frame_resize" "start"; + } + program { + name: "video_resize_stop"; + signal: "mouse,up,*"; + source: "video_resizer"; + action: SIGNAL_EMIT "frame_resize" "stop"; + } + } + } + + group { + name: "video_controller/reflex"; + parts { + // need swallow parts: + // "video_swallow" + // + // need txt parts: + // "video_speed_txt" + // "video_progress_txt" + // + // need dragables: + // "video_progress" horizontal + // "video_speed" vertical + part { + name: "video_swallow"; + mouse_events: 0; + type: SWALLOW; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 0.0; + offset: -8 23; + } + rel2 { + to: "video_frame_right"; + relative: 0.0 1.0; + offset: 7 -25; + } + } + } + + part { + name: "swallow_center"; + type: RECT; + description { + state: "default" 0.0; + visible: 0; + rel1 { + to: "video_swallow"; + relative: 0.5 1.0; + } + rel2 { + to: "video_swallow"; + relative: 0.5 1.0; + } + } + } + part { + name: "swallow_mirror"; + type: PROXY; + mouse_events: 0; + description { + state: "default" 0.0; + source: "video_swallow"; + rel1 { + to: "video_swallow"; + } + rel2 { + to: "video_swallow"; + } + perspective { + zplane: 0; + focal: 1000; + } + color: 255 255 255 96; + map { + on: 1; + smooth: 0; + alpha: 1; + rotation { + center: "swallow_center"; + x: 100; + } + } + } + } + + part { + name: "video_frame_left"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + relative: 0.0 1.0; + offset: 32 -1; + } + image { + border: 0 0 33 33; + normal: "video_frame_left.png"; + } + } + } + part { + name: "video_frame_right"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + relative: 1.0 0.0; + offset: -32 0; + } + rel2 { + relative: 1.0 1.0; + offset: -1 -1; + } + image { + border: 0 0 33 33; + normal: "video_frame_right.png"; + } + } + } + part { + name: "video_frame_top"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 0.0; + offset: 0 0; + } + rel2 { + to: "video_frame_right"; + relative: 0.0 0.0; + offset: -1 31; + } + image { + normal: "video_frame_top.png"; + } + } + } + part { + name: "video_frame_bottom"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 1.0; + offset: 0 -32; + } + rel2 { + to: "video_frame_right"; + relative: 0.0 1.0; + offset: -1 -1; + } + image { + normal: "video_frame_bottom.png"; + } + } + } + part { + name: "video_speed_txt"; + type: TEXT; + mouse_events: 0; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_bottom"; + relative: 0.0 0.0; + offset: 0 8; + } + rel2 { + to: "video_frame_bottom"; + relative: 1.0 1.0; + offset: -1 -13; + } + color: 0 0 0 255; + text { + text: "Video Speed"; + font: "Sans"; + size: 6; + align: 1.0 0.5; + }; + } + } + part { + name: "video_progress_confine"; + mouse_events: 0; + type: RECT; + description { + state: "default" 0.0; + fixed: 1 1; + min: 1 18; + align: 0.5 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 1.0; + offset: 0 -25; + } + rel2 { + to: "video_frame_right"; + relative: 0.0 1.0; + offset: -1 -25; + } + color: 0 0 0 0; + } + } + part { + name: "video_progress"; + type: RECT; + mouse_events: 1; + dragable { + x: 1 1 0; + y: 0 0 0; + confine: "video_progress_confine"; + } + description { + state: "default" 0.0; + fixed: 1 1; + min: 34 18; + rel1 { + to: "video_progress_confine"; + relative: 0.5 0.5; + offset: 0 0; + } + rel2 { + to: "video_progress_confine"; + relative: 0.5 0.5; + offset: 0 0; + } + color: 0 0 0 0; + } + } + part { + name: "video_progress_img"; + mouse_events: 0; + description { + state: "default" 0.0; + fixed: 1 1; + min: 42 26; + rel1 { + to: "video_progress"; + relative: 0.5 0.5; + offset: 0 0; + } + rel2 { + to: "video_progress"; + relative: 0.5 0.5; + offset: 0 0; + } + image { + normal: "h_slider.png"; + } + } + } + part { + name: "video_speed_confine"; + mouse_events: 0; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_left"; + relative: 1.0 0.0; + offset: 0 24; + } + rel2 { + to: "video_frame_left"; + relative: 1.0 1.0; + offset: 48 -49; + } + color: 0 0 0 0; + } + } + part { + name: "video_speed"; + mouse_events: 1; + dragable { + x: 0 0 0; + y: -1 1 0; + confine: "video_speed_confine"; + } + description { + state: "default" 0.0; + fixed: 1 1; + min: 24 24; + rel1 { + to: "video_speed_confine"; + relative: 0.5 0.5; + offset: 0 0; + } + rel2 { + to: "video_speed_confine"; + relative: 0.5 0.5; + offset: 0 0; + } + image { + normal: "knob.png"; + } + } + } + part { + name: "video_play"; + mouse_events: 1; + description { + state: "default" 0.0; + fixed: 1 1; + min: 24 24; + rel1 { + to: "video_frame_bottom"; + relative: 0.0 0.5; + offset: 0 0; + } + rel2 { + to: "video_frame_bottom"; + relative: 0.0 0.5; + offset: 0 0; + } + image { + normal: "knob.png"; + } + } + } + part { + name: "video_pause"; + mouse_events: 1; + description { + state: "default" 0.0; + fixed: 1 1; + min: 24 24; + rel1 { + to: "video_frame_bottom"; + relative: 0.5 0.5; + offset: 0 0; + } + rel2 { + to: "video_frame_bottom"; + relative: 0.5 0.5; + offset: 0 0; + } + image { + normal: "knob.png"; + } + } + } + part { + name: "video_stop"; + mouse_events: 1; + description { + state: "default" 0.0; + fixed: 1 1; + min: 24 24; + rel1 { + to: "video_frame_bottom"; + relative: 1.0 0.5; + offset: 0 0; + } + rel2 { + to: "video_frame_bottom"; + relative: 1.0 0.5; + offset: 0 0; + } + image { + normal: "knob.png"; + } + } + } + part { + name: "video_mover"; + mouse_events: 1; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_top"; + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + to: "video_frame_top"; + relative: 1.0 1.0; + offset: -1 -1; + } + color: 255 20 20 20; + } + } + part { + name: "video_resizer"; + mouse_events: 1; + type: RECT; + description { + state: "default" 0.0; + rel1 { + to: "video_frame_right"; + relative: 0.0 1.0; + offset: 0 -31; + } + rel2 { + to: "video_frame_right"; + relative: 1.0 1.0; + offset: -1 -1; + } + color: 20 20 255 20; + } + } + part { + name: "video_progress_txt"; + type: TEXT; + mouse_events: 0; + effect: OUTLINE; + description { + state: "default" 0.0; + align: 1.0 1.0; + fixed: 1 1; + rel1 { + relative: 1.0 1.0; + offset: -2 -2; + } + rel2 { + relative: 1.0 1.0; + offset: -2 -2; + } + color: 255 255 255 255; + color2: 0 0 0 255; + text { + text: "XX:XX:XX / XX:XX:XX"; + font: "Sans"; + size: 10; + align: 1.0 1.0; + min: 1 1; + }; + } + } + } + programs { + // emit signals: + // "video_control" "play" + // "video_control" "pause" + // "video_control" "stop" + // "drag" "video_progress" + // "drag" "video_speed" + // + // get signals: + // "video_state" "play" + // "video_state" "pause" + // "video_state" "stop" + program { + name: "video_play"; + signal: "mouse,down,1"; + source: "video_play"; + action: SIGNAL_EMIT "video_control" "play"; + } + program { + name: "video_pause"; + signal: "mouse,down,1"; + source: "video_pause"; + action: SIGNAL_EMIT "video_control" "pause"; + } + program { + name: "video_stop"; + signal: "mouse,down,1"; + source: "video_stop"; + action: SIGNAL_EMIT "video_control" "stop"; + } + program { + name: "video_move_start"; + signal: "mouse,down,*"; + source: "video_mover"; + action: SIGNAL_EMIT "frame_move" "start"; + } + program { + name: "video_move_stop"; + signal: "mouse,up,*"; + source: "video_mover"; + action: SIGNAL_EMIT "frame_move" "stop"; + } + program { + name: "video_resize_start"; + signal: "mouse,down,*"; + source: "video_resizer"; + action: SIGNAL_EMIT "frame_resize" "start"; + } + program { + name: "video_resize_stop"; + signal: "mouse,up,*"; + source: "video_resizer"; + action: SIGNAL_EMIT "frame_resize" "stop"; + } + } + } +#endif +} diff --git a/data/tiles.png b/data/tiles.png new file mode 100644 index 0000000000000000000000000000000000000000..7e92bd15faba8f14ca68fa89fa7af5d3d9d37d6a GIT binary patch literal 3026 zcmZXWeK^y5AIFDvwuqS}b;3fW&hn5tTAoJcMmi%x$V{maak?ckhAd4dONE?+DP_sS zG>;`uqvI(Lr95`W7$ek7)7ECc`{#7dx$f)SfBb&G@AbW|@9%qE@9Xt>eLgfdf}^VP z_sS3mMAg{|?+$(w*B?z4$kmm^z$JjngTDCful59+t}ncCahk*922woz@n6V ztjHXfAj7W8SEZl7d>S7Z8ylM&Z=#$ET`pteDDqq)kw~CYv;kLrK>FoVA)FYs=*aQd z3A-s~u~^>s9o4ou_M_GA)ley>fCkdeFL~^OpZ7GrQS;pla_l-QKAcL~1JE@xdeXK| z7n;$+*VRf6E``8qUUxJa(bG@CN;yp%S|jhjS$TfvdP$`co@boFGB-P;daE`BO0d)} z5U}|EwG)(y)t^0idfLcgR4lfAHfimr@Q{X{8NR+pdn5#39fA>t6jllNsT1@WN;Leg zk|Xxn1=@&#&0+;A(Bbsp!OV67mo-J1!0IZR@mwJHpL&x=HRUZbRFXN{Y|a17cW!@sbEDmPnoo5Ii7I{liZu1;_eS-fFmuKE%rT6b9FMa%fp5jc0H(IvCfZ z(k0R(B1MrEFwB?uNho*f;0wzeV22yTZ%%*g{}nSV3??S&R4hDo^Ae-mfx-^ztgbL5 zRS7?7OkVTeYBHjSTjrdyjq{_2 zcgwmFQIU3|%Dqpl(wa9&s!&eQjhPbEE1T%;!E|vIMiwp$5J7yFkVo{{dKSf6@3PM^ zoIYwc37Ck1Jwy3tS%{0C5oX{|1N0#?9=5&{cTk;dPjNQ=Ok||HVjDC6(n_U_u2ylC zoKk7qFcI3lPLviP{?s%cHcio19K1_8;v{~^Z69{mo539oxBhA9!%6CUVK~hZA&*aK2b_! z6b!;P@3gYcZzIUq+PpSnTB-l5Bpkgl&RALNU8-dOONh5j~g3u7*(l`wPXpj zTrC$g6J(}6LLpMd(Aj3z2rW0)*m5tfjj5yNCLU_Js3M2G&;DfKH#rNX@rX+y-eTCY zE7UilQj#Txr{4UmXnx~aeELASfQ2sl&n;j?k3=A+6k@(uH{TLhwGvV^Gkq@H0jt1u zd{>tc7pZ;8Zi{dSB;!aBrY8|Rg_vQ$t1>c?Xf7Fg=0$s;GH@AQw*ycblr9V~2lZxz z_zSK)gGP6Hw_LlZ%tM?#CU`%wRZ@%hJGn2mIumlP&9RQt^bR_@Nr^*Wh4t5y_@oY$)EAG0!9JhqQk ziEzJ3kPi$vI4)994r%_d7!qoeGsC&7TH z^swE4C*r0ix<#G1yWm01o~{zz{CAiHt}D98Cm~ME_zY>7bb&ULLtTSG?R0x_O)g2H z%EkP=)q}l;7fs)|*l>IbXo1W9k37pk;VwuwR@*eE<-?esKN!~7_22d;mCi|4+R&+x z-#r+<+tMXw{&);$-}L+Z|I|u26!fySp`QdD2Z=Z)bvbQ8oL2%t(_%A}pR_EC=!jkOILKP7oaZOQ|ZTBoJrEUZQfd;u)`wH|@bykY)Z1dSdE zcQzpnJR0L;7nOmpQ~jWFEuk;L{ix|i*l`We5wwc?W-jSM&=GU>DL!&o`jqi5`$p)t zTePr;TO$7);l*BJzT3+!gGYxHnw2>Uv6CH z&oNfNo{LZPMHl4r$3@Z&enY>3o&eD->Ac5q3&lNq`v!ljK6NDLLuB`B3*DaxDuA%k z0`+ARF!xC@s-AkBmzfp@hrMJXv5U`pvieD*Q-1;4agCf}px7|GP}|1zUu(~YMmyMl zOVwW^AYA1igyOB{{@1B$bq}abGLrKq#o%ahn3D5ZIb?>RW@`{699~ZFI@K)4_)#@cQyU^-lcJLC0dHNN%s)1 zM!3`V)s)Hl2#RIcqeQjJox+154^KF;mWvbq;uW9lc+zJt?fmQ6yC!SII=(5L(D=nX zj?73e1Lv!CKE^8(V1d^yf7t>i24)DZ`6A>WYtmPba>m0-^lC@pDeK!<%cSilTS;Q8 zOQt3{q(BuQ=qap5zq?*8SR4u<1bD(pvVN>LiEb8UYupxsZ(hqd6DVrk`AyeL!Wz z>gqyfK!-W5TbQ0DS`i0g6 z0}7Q&_0ZhX0&J4eZ{72o->*scPdJCZLNJ$gbG?e875blfJBCLmJnF3leb$K$yM8&_ z6@_fbKRfTZnM!%um#X64H{>O6*KOYVR_>mY4xR+{J16O7FexkZ0K%GaBigYI#|39~ Nh_eF$Uw(*`{9h)$Fb@C# literal 0 HcmV?d00001 diff --git a/data/video_frame_bottom.png b/data/video_frame_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..97eb5dd5a6e1ce4805bda7df1bbb0cc6ff8ed6ae GIT binary patch literal 514 zcmV+d0{#7oP)WFU8GbZ8({Xk{QrNlj4iWF>9@00Cx6L_t(|+U=RaZi6ro zM4#!ZQdOx^)xYmQapcM^?I9{satfk&dkC!}O0WUbP|RMeEaRD-#gS|STad(V{vNoC zwE+S=G~*{=o4oD7s)Nhi*vpvu5&<583aA_7dWB3EY<_HwMu6vz23Su4v(T08TW2D` zOSAl4D`1UbOi>i7diHDW`Ne<#c8$LHK3qtyF*tKL9CS{huIC{*Le(NwRsCuA=YFF; zxJ!%_MG>?BU*Rd^6rOfYj>qGy1x@7+G4?%^)9G{*;U$;{kh-p;HLt2jS(g9C^v^CQ zU=6b0?A7F$FgU)oy~3+&r(_5c6?07*qoM6N<$ Ef{oZA2Z03CEi zSad^gZEa<4bO1wgWnpw>WFU8GbZ8({Xk{QrNlj4iWF>9@00&D+L_t(|+U;9SZxcxx zeyY3r!*=Z02rFZetdVDhxPXw5P=-lXbIWC=9WfFTKVbJKO#T6PPV)!2&1J89inJGI zfPnB}_pp)JaWss`f=T?*UEN*PwTE;y6^|Xv^B5ww?m!V?O5N zlm|KGyoAgsnE}8|K1p&-rVW55iLB(44gfKx1;9>{*hz9d6ex2V08~;3fbF`jyScg9 z*x1uT`rfeyRQ3%VHg&s^wdQF)z#J2KR$W#f-wmI2SDZCy?a*~WB-*W9Fxp>d2Ma2F;4P0j-?PnhG8g! zAdrkP$rzLUeqWLkvON!AVQ+8mhibL@mr*xLDG`Ptq?Cx`7yuxINWW8Jk#*i}0Pfb- z)}N0{E`&f7Mc|x+a}FsbIOj)_ODQw21vY^E>gwvnM~@!;XVgt$7$S-yL{S9a_YnjE zq9{Tbh7dxe)yP@_lBk*U;K76Mj!PZ{0fHdF!NCFA?Ka-MdxuV^1JCmiMNwLTIF2(_ zfC5->UANTl_jiUVnh*kvG5EfZw{PEKcXt;%J3DB#T6pv34Se5EIY1H-rWpZPo12@B zVacVGY1t1B4zRnsix)3mpxJCHZ2!>(6FbtTc2|~!&0Ehyxv9a;hup1QF z7-ML++j#l%C7R79wzs#@YPFc}`@aey_N0_P03SdIAfy>uj{>0edj0ERPp`_P) z4I|@XG_nGE3{oTso&eCngjuIxWb$LGATu7KKHj8TbUmBGXSj!Qburgs(`m@a@xL1Y0y&U^*3%>C3jkQKyKyWmtRaIU)` zQ}R>gKo$_^lLM#T1v4e#sN^#v;YpItM2hD^bS5frszNkhj^|x46Anz8{L|;asQ1Fp zrwh&`2WI+W@}UZx|4r$n`@xT1ftizV*zbd9LW<`?^!Y4CXIh9p-!7ObfC+x6KBpYW zx)(UVIxt@gW~zjfw&Ewn0Xfc=Y^J{xPO=&O=zGGMOYw)u_bHH&j0->xyBu-}?cFfv_wq4ZJrp4-1;rPZ%qQjB?8iwxDU6 zpp?ROUF32(=*jTjYiz5a8J=DOkU1xNQj!}blA3yVzG!?t%l|0Wi%R%WgHq{T^w3La{vlSESO^gP*0G% zd-v|mQmNEXz9Gig5tpRKepr@;rKP1}v)TNGbIx#RWDz)YP!IrSRsinp+qW-XzI=II ziP0bz2q7SZz_Kj3u8XCmC3k&&eI=jIN3UMJ>I6Z+wXU$obyT_lN&qT%?%cU{|Ni|S zZQF)n7>J?>jIq?JsQ@WI8Rs0169nAe$BdDy6jR^}1K9)oyEswUm^qGj!`F zrSwQr#T6mM*cBiNYfAts)oS(9!-o(5VVWj#xg0FZI`WToBI?>;S(dJlP$H3K<)i>C z&+}+LpZ{%TW#vyn5Tp(|!!V90qY&bVt6G^}mF<@?mI(mx{)7bG-roM-jT<)_j^q3x z48vnrL)~+#lvI6Y0U!rtl|Fs?^j|k`-u#AhUSNzt36$1)wQddRoTwy!hF(XFt_ywM$aUOWkf4 z-EJ4XUJt!q55Dii^Ssn?%@|An?)Uqc$lkBI0>A|T7jE6UwSMi|wZEm-eM({5HXO%+ zWmzyyGuroHAM^2k{2!ecL9Z0dxW)hg002ovPDHLk FV1n~Pq?rH! literal 0 HcmV?d00001 diff --git a/data/video_frame_right.png b/data/video_frame_right.png new file mode 100644 index 0000000000000000000000000000000000000000..1cefbafcefe96a880e07908c4e95d56cce8f3c3d GIT binary patch literal 2441 zcmV;433m30P)WFU8GbZ8({Xk{QrNlj4iWF>9@00`|#L_t(|+U;9SYa81c zerD#3M)o+L#D(izD5TI*vdO05uDZ^~+i?Ft!F1pKU3B3^A??-_`Ue78l>|x_H|-4< z$}ME$#!euK6UmljTk|1lKF*mlUHH6{qwz?V9m&4A)xe8J)}Z$}&-*d&$j<@h$NZQd z7kn51tkU0dWzb${b}#@-CFeSbOub5VE~gEO0k}HCxhy#r>YS@rF)aYg>Rf8h^;MHI zUb0kumVQzWnXIe}3@b!9O~kP5>a%EG_{$9RMLj4gh(c zLrMwGIkGGR=Nz1K#Bq#%zYpK{(eL;1@ZrNhZftCP3!tyrKm(MXCQ*$}r;}${2E#Cr z=XqgP6Nda&wy6kuck|Y7=9BG#@I&GYPE_twr#_*EI5t>+qO}w z)r#DpTrdm+j4`;b3)gjVaBzS-ckcY|#ful4Ns^>muSm46IkG&h+qZ9j({8tMaBu+M z_c0g@kful18-`IBu|a^cEJK>6MRlZU+HbX54XslOt$mMd+m`FP-!z*|v|26f@9)F+ zeZ+BmL=R&HE0$$J>siS2yZ~@`cnI6Jf3>x>^-rx$lMxVE8G`NY?IOcn*Twbg*O8_v zY}>}d!U9~^MZI1x7$FdbVZd=5EG{mBF$O86b@l4iFFnuesh&XP7^{0uB@1k8YwK?S zOftrpbL-ZvFYn#E_v@9Fl`B$8n5GHF7&zx2sk1CF#!#=H*M8}F-i|6o zM$<;C&g)t) zV9F{>(gg59SwmS9z+N23jc3oEeShiFCDiM6)a!Mara2S_svO(4VHgH1%lbk&rxGL< zEaj^bKvQ$Rr2@Z5Q_g%d(JVA8-ApX%1C|a$M8sx3urC1hB7NU@Q7u%38))QG%vv4)p^X zWb!;OTDZ1yRsvvDB_adREdf|iwG05vvMiXUS?Rpo7Zd=iv}*Gt06ld9Qvirx8^D4} zuHt4y@h^j*P-qUToL7c``n07r3#N@)LpP&Q3~2Ao3dhDM5KKF#X8=oUqkNRp@+&b@ z;m{m=J1)J~=YO(ES6=>JeZ?a~P=!u^D3Mh&!3m(u(@e!x7t0ceNt~Ya{8@EA7H#p( z<5sTQ2*<`*7&wk*g!3_M7@rb?GdrI!B&TP92GlC&pL$Hhz!X+&Of>|bO8c3UaMG4M z^$?u05zUT)S%l&9%7JM+p9sLLVt?vJG^=o&ItQj*it{S?@mIk~u^%%R&U0Y4ec*(7 zaJHTB+()umIX~4%M!yrz8_|U|q8~K_7dn)lODmq`RP=d_WRp5SmyzuMw+dzjV%`a- z)(2*KJD%j%vJ0t#a|yvL=fN}mL~|j(l1(}f&a4&B%K7}sXljkbOPjjpCDJr4q@e0LsaalO#{ewhxQxdI z;I6H$edRb#A$BE|Ev-JwvO<3v$1ynPJsg*W%acNI4HZJBn>TMRudc3s%@{)zMTPR3 zoJ%Q@BnhG@La*0Dk|ape^bjAlCli5S0B&di*viVv)wQ*?uU1!AzrJzf#?MJ_8buL= z5Jkdq&PjD$01!g#VpvTnFs#Zy4&eFo=iif9i7^JpaSHh!sj9;;B#H~_(=kp2uvKu@H`KVMgwo(zD1+aKoA7r zoIeK;XaEKkp{OpyBuPfLRRTdV4}t*AW)pATyur@S4!Yeg(lq@5;1z~d_Bs;;pt=)M zZR-q>Vv<78@Au((9`^S3u(Pv+ckkYz-EJd_qCSA{Fs!a8g?+3sFmm?=OOj;hMxqPd zlO#bHhVXsAhTa}|q1Wpn2m<)Nk01yT$1$=jd#+;c zE60Z#2)`l(W2Yjvxw$!%^|X32CHt2`h#yp`(JFn7_O7x(B_VC|IC19_1uIg~HqPDLk8_}*O;XvyFCmsfXzm}$!9LF~}B^rQ%T4h+WGi`EV zI8svUW0ZbB7Z~2$6l)nim2Ex@N4j#9Rvlf_M_Y3+0>sQWJYM*g&-pPwF8uf(5>0daL+f?#00000NkvXX Hu0mjf05EQ9 literal 0 HcmV?d00001 diff --git a/data/video_frame_top.png b/data/video_frame_top.png new file mode 100644 index 0000000000000000000000000000000000000000..9317a61478ad9f86d036807e5dcbae40fdc08db8 GIT binary patch literal 471 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQfx`y?k)^7K`_oGtPv=}S>O>_ z%)r1c48n{Iv*t(u1=&kHeO=iv^N5QISx7~{zW@}HEpd$~an8@pP0cG|a4t$sEJ;mK zD9jyK!lUM(|I(B+QG{NFM`*Ld#C^~`q}L_|R#Rh#t=%Pm>QWAXwI@)kOjZg4fX zYxv#j#LxfWpjhNn4hP9(pL6^NwZ6wHR5N^fZoXtM^VVzk>(*PYpXvNeug#~-cT@CS z=iKM7ChmJ*&O68HqkY){i@w?H-)>u9eZ-g|(U$P||E5QVJH4)#9&AijT+?dybbINV z(|Q+7&aNr;QKhWuGaq=u_TVIwg|+MiZkDfC8Rf+q3j1;xY?#%TGjC%4z||wiAp0Z8@alHgg_U7U zdwdxT7$+~|P%?8@J+Pa#peQWP-ESUKi|Nl$hV3o2(iThX7>_>OSN|?6Kol6>44$rj JF6*2UngF?wws-&l literal 0 HcmV?d00001 diff --git a/data/whb.png b/data/whb.png new file mode 100644 index 0000000000000000000000000000000000000000..5f141d4b6d5756cbcf3620104f51ebc102d21616 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^nLy0J!3HFMXQL70(Y)*K0-AbW|YuPgf%W*!bbuC-?xs)0hXC9V-A&iT2ysd*&~&PAz-C8;S2 z<(VZJ3LzP(3hti10q;{(^MDGCJzX3_DsH{K<|xQuAaLlw1PXv#B`vy>>f4EB{WB=$%0A44$rjF6*2UngC8CJbVBE literal 0 HcmV?d00001 diff --git a/data/window_inner_shadow.png b/data/window_inner_shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..93410708e5829f2de6eb57b95f7ebf2f14f38a97 GIT binary patch literal 30426 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 literal 0 HcmV?d00001 diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 0000000..907be04 --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,138 @@ +PROJECT_NAME = Emotion +PROJECT_NUMBER = @PACKAGE_VERSION@ +OUTPUT_DIRECTORY = . +INPUT = @top_srcdir@/src/lib \ + @srcdir@/examples.dox +IMAGE_PATH = @srcdir@/img +OUTPUT_LANGUAGE = English +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = @srcdir@/head.html +HTML_FOOTER = @srcdir@/foot.html +HTML_STYLESHEET = @srcdir@/e.css +HTML_ALIGN_MEMBERS = YES +ENUM_VALUES_PER_LINE = 1 +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = YES +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = NO +SHOW_INCLUDE_FILES = NO +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 2 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = NO +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = @top_srcdir@/src/examples @top_srcdir@/src/bin +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 2 +IGNORE_PREFIX = emotion_ _emotion_ Emotion_ _Emotion_ EMOTION_ _EMOTION_ +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +GENERATE_MAN = YES +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = YES +GENERATE_XML = NO +XML_SCHEMA = +XML_DTD = +GENERATE_AUTOGEN_DEF = NO +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = NO +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = NO +COLLABORATION_GRAPH = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +SEARCHENGINE = NO diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..f5cdc41 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,33 @@ +MAINTAINERCLEANFILES = Makefile.in + +.PHONY: doc + +PACKAGE_DOCNAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc + +if EFL_BUILD_DOC + +doc-clean: + rm -rf html/ latex/ man/ xml/ $(top_builddir)/$(PACKAGE_DOCNAME).tar* + +doc: all doc-clean + $(efl_doxygen) + cp $(srcdir)/img/* html/ + cp $(srcdir)/img/* latex/ + rm -rf $(PACKAGE_DOCNAME).tar* + mkdir -p $(PACKAGE_DOCNAME)/doc + cp -R html/ latex/ man/ $(PACKAGE_DOCNAME)/doc + tar cf $(PACKAGE_DOCNAME).tar $(PACKAGE_DOCNAME)/ + bzip2 -9 $(PACKAGE_DOCNAME).tar + rm -rf $(PACKAGE_DOCNAME)/ + mv $(PACKAGE_DOCNAME).tar.bz2 $(top_builddir) + +clean-local: doc-clean + +else + +doc: + @echo "Documentation not built. Run ./configure --help" + +endif + +EXTRA_DIST = Doxyfile.in $(wildcard img/*.*) e.css head.html foot.html examples.dox diff --git a/doc/e.css b/doc/e.css new file mode 100644 index 0000000..2dd6b44 --- /dev/null +++ b/doc/e.css @@ -0,0 +1,273 @@ +/* + Author: + Andres Blanc + DaveMDS Andreoli + + Supported Browsers: + ie7, opera9, konqueror4 and firefox3 + + Please use a different file for ie6, ie5, etc. hacks. +*/ + + +/* Necessary to place the footer at the bottom of the page */ +html, body { + height: 100%; + margin: 0px; + padding: 0px; +} + +#container { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -53px; +} + +#footer, #push { + height: 53px; +} + + +* html #container { + height: 100%; +} + +/* Prevent floating elements overflowing containers */ +.clear { + clear: both; + width: 0px; + height: 0px; +} + +/* Flexible & centered layout from 750 to 960 pixels */ +.layout { + max-width: 960px; + min-width: 760px; + margin-left: auto; + margin-right: auto; +} + +body { + /*font-family: Lucida Grande, Helvetica, sans-serif;*/ + font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif +} + +/* Prevent design overflowing the viewport in small resolutions */ +#container { + padding-right: 17px; + padding-left: 17px; + background-image: url(head_bg.png); + background-repeat: repeat-x; +} + +/****************************/ +/* Top main menu */ +/****************************/ +#header_logo { + background-image : url(logo.png); + width : 61px; +} + +#header_logo a { + position : absolute; + border : 0px; + background-color : transparent; + top : 0px; + width : 60px; + height : 60px; +} + +#header_menu { + background-image : url(header_menu_background.png); + font : normal 10pt verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif; + text-align : right; +} + +#header_last { + background-image : url(header_menu_background_last.png); + width : 15px; +} + +td.nav_passive { + background : url(header_menu_unselected_background.png) 0 0 no-repeat; + height : 63px; + font-family : "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif; + font-size : 11px; + padding : 20px 10px 20px 10px; + vertical-align : middle; +} + +td.nav_active { + background : url(header_menu_current_background.png) 0 0 no-repeat; + height : 63px; + color : #646464; + font-family : "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif; + font-size : 11px; + font-weight : bold; + padding : 20px 10px 20px 10px; + vertical-align : middle; +} + +#header_menu a { + display : block; + text-decoration : none; + cursor : pointer; + color : #cdcdcd; +} + + + +#header { + width: 100%; + height: 102px; +} + +#header h1 { + width: 63px; + height: 63px; + position: absolute; + margin: 0px; +} + +#header h1 span { + display: none; +} + +#header h2 { + display: none; +} + +/* .menu-container is used to set properties common to .menu and .submenu */ +#header .menu-container { +} + +#header .menu-container ul { + list-style-type: none; + list-style-position: inside; + margin: 0; +} + +#header .menu-container li { + display: block; + float: right; +} + +#header .menu { + height: 63px; + display: block; + background-image: url(menu_bg.png); + background-repeat: repeat-x; +} + +#header .menu ul { + height: 100%; + display: block; + background-image: url(menu_bg_last.png); + background-repeat: no-repeat; + background-position: top right; + padding-right: 17px; +} + +#header .menu li { + height: 100%; + text-align: center; + background-image: url(menu_bg_unsel.png); + background-repeat: no-repeat; +} + +#header .menu a { + height: 100%; + display: block; + color: #cdcdcd; + text-decoration: none; + font-size: 10pt; + line-height: 59px; + text-align: center; + padding: 0px 15px 0px 15px; +} + +#header .menu li:hover { + background-image: url(menu_bg_hover.png); + background-repeat: no-repeat; +} + +#header .menu li:hover a { + color: #FFFFFF; +} + +#header .menu li.current { + background-image: url(menu_bg_current.png); + background-repeat: no-repeat; +} + +#header .menu li.current a { + color: #646464; +} + + +/* Hide all the submenus but the current */ +#header .submenu ul { + display: none; +} + +#header .submenu .current { + display: block; +} + +#header .submenu { + font: bold 10px verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif; + margin-top: 10px; +} + +#header .submenu a { + color: #888888; + text-decoration: none; + font-size: 0.9em; + line-height: 15px; + padding:0px 5px 0px 5px; +} + +#header .submenu a:hover { + color: #444444; +} + +#header .submenu li { + border-left: 1px solid #DDDDDD; +} + +#header .submenu li:last-child { + border-left: 0; +} + +#header .doxytitle { + position: absolute; + font-size: 1.8em; + font-weight: bold; + color: #444444; + line-height: 35px; +} + +#header small { + font-size: 0.4em; +} + +#footer { + background-image: url(foot_bg.png); + width: 100%; +} + +#footer table { + width: 100%; + text-align: center; + white-space: nowrap; + padding: 5px 30px 5px 30px; + font-size: 0.8em; + font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif; + color: #888888; +} + +#footer td.copyright { + width: 100%; +} + diff --git a/doc/emotion.css b/doc/emotion.css new file mode 100644 index 0000000..6117b39 --- /dev/null +++ b/doc/emotion.css @@ -0,0 +1,178 @@ +td.md { + background-color: #ffffff; + font-family: monospace; + text-align: left; + vertical-align: center; + font-size: 10; + padding-right : 1px; + padding-top : 1px; + padding-left : 1px; + padding-bottom : 1px; + margin-left : 1px; + margin-right : 1px; + margin-top : 1px; + margin-bottom : 1px +} +td.mdname { + font-family: monospace; + text-align: left; + vertical-align: center; + font-size: 10; + padding-right : 1px; + padding-top : 1px; + padding-left : 1px; + padding-bottom : 1px; + margin-left : 1px; + margin-right : 1px; + margin-top : 1px; + margin-bottom : 1px +} +h1 +{ + text-align: center; + color: #333333 +} +h2 +{ + text-align: left; + color: #333333 +} +h3 +{ + text-align: left; + color: #333333 +} +a:link +{ + text-decoration: none; + color: #444444; + font-weight: bold; +} +a:visited +{ + text-decoration: none; + color: #666666; + font-weight: bold; +} +a:hover +{ + text-decoration: none; + color: #000000; + font-weight: bold; +} +a.nav:link +{ + text-decoration: none; + color: #444444; + font-weight: normal; +} +a.nav:visited +{ + text-decoration: none; + color: #666666; + font-weight: normal; +} +a.nav:hover +{ + text-decoration: none; + color: #000000; + font-weight: normal; +} +a.qindex:link +{ + text-decoration: none; + color: #444444; + font-weight: normal; +} +a.qindex:visited +{ + text-decoration: none; + color: #666666; + font-weight: normal; +} +a.qindex:hover +{ + text-decoration: none; + color: #000000; + font-weight: normal; +} +p +{ + color: #000000; + font-family: sans-serif; + font-size: 10; +} +body { + background-image: url("hilite.png"); + background-repeat: no-repeat; + background-position: left top; + background-color: #dddddd; + color: #000000; + font-family: sans-serif; + padding: 8px; + margin: 0; +} +div.fragment +{ + background-image: url("hilite.png"); + background-repeat: no-repeat; + background-position: left top; + border: thin solid #888888; + background-color: #eeeeee; + padding: 4px; + text-align: left; + vertical-align: center; + font-size: 12; +} +hr +{ + border: 0; + background-color: #000000; + width: 80%; + height: 1; +} +dl +{ + background-image: url("hilite.png"); + background-repeat: no-repeat; + background-position: left top; + border: thin solid #aaaaaa; + background-color: #eeeeee; + padding: 4px; + text-align: left; + vertical-align: center; + font-size: 12; +} +em +{ + color: #334466; + font-family: courier; + font-size: 10; + font-style: normal; +} + +div.nav +{ + border: thin solid #000000; + background-color: #ffffff; + padding: 1px; + text-align: center; + vertical-align: center; + font-size: 12; +} +div.body +{ + border: thin solid #000000; + background-color: #ffffff; + padding: 4px; + text-align: left; + font-size: 10; +} +div.diag +{ + border: thin solid #888888; + background-color: #eeeeee; + padding: 4px; + text-align: center; + font-size: 8; +} diff --git a/doc/examples.dox b/doc/examples.dox new file mode 100644 index 0000000..5e193f1 --- /dev/null +++ b/doc/examples.dox @@ -0,0 +1,104 @@ +/** + * @page Examples Examples + * + * Here is a page with some Emotion examples explained: + * + * @li @ref emotion_basic_example_c + * @li @ref emotion_signals_example.c "Emotion signals" + * @li @ref emotion_test_main.c "emotion_test - full API usage" + * + */ + +/** + * @page emotion_basic_example_c Emotion - Basic library usage + * + * This example shows how to setup a simple Emotion object, make it start + * playing and register a callback that tells when the playback started. See @ref + * emotion_basic_example.c "the full code here". + * + * @dontinclude emotion_basic_example.c + * + * We start this example by including some header files that will be necessary + * to work with Emotion, and to display some debug messages: + * + * @until stdio.h + * + * Then a callback will be declared, to be called when the object starts its + * playback: + * + * @until } + * + * Some basic setup of our canvas, window and background is necessary before + * displaying our object on it. This setup also includes reading the file to be + * opened from the program's argument list. Since this is not directly related + * to Emotion itself, we are just displaying the code for this without an + * explanation for it: + * + * @until evas_object_show(bg); + * + * Finally, we start the Emotion part. First we have to create the object in + * this canvas, and initialize it: + * + * @until emotion_object_init + * + * Notice that we didn't specify which module will be used, so emotion will use + * the first module found. There's no guarantee of the order that the modules + * will be found, so if you need to use one of them specifically, please be + * explicit in the second argument of the function emotion_object_init(). + * + * Now the callback can be registered to this object. It's a normal Evas smart + * object callback, so we add it with evas_object_smart_callback_add(): + * + * @until NULL + * + * The object itself is ready for use, but we need to load a file to it. This is + * done by the following function: + * + * @until file_set + * + * This object can play audio or video files. For the latter, the image must be + * displayed in our canvas, and that's why we need to add the object to the + * canvas. So, like any other Evas object in the canvas, we have to specify its + * position and size, and explicitly set its visibility. These are the position + * and dimension where the video will be displayed: + * + * @until evas_object_show + * + * Since the basic steps were done, we can now start playing our file. For this, + * we can just call the basic playback control function, and then we can go to + * the main loop and watch the audio/video playing: + * + * @until main_loop_begin + * + * The rest of the code doesn't contain anything special: + * + * @until } + * + * This code just free the canvas, shutdown the library, and has an entry point + * for exiting on error. + */ + + +/** + * @example emotion_basic_example.c + * This example show how to create and play an Emotion object. See @ref + * emotion_basic_example_c "the explanation here". + */ + +/** + * @example emotion_signals_example.c + * + * This example shows that some of the information available from the emotion + * object, like the media file play length, aspect ratio, etc. can be not + * available just after setting the file to the emotion object. + * + * One callback is declared for each of the following signals, and some of the + * info about the file is displayed. Also notice that the order that these + * signals are emitted can change depending on the module being used. Following + * is the full source code of this example: + */ + +/** + * @example emotion_test_main.c + * This example covers the entire emotion API. Use it as a reference. + */ diff --git a/doc/foot.html b/doc/foot.html new file mode 100644 index 0000000..d43cf8f --- /dev/null +++ b/doc/foot.html @@ -0,0 +1,18 @@ + +
+ + + + + + + + + + + diff --git a/doc/head.html b/doc/head.html new file mode 100644 index 0000000..16696c4 --- /dev/null +++ b/doc/head.html @@ -0,0 +1,68 @@ + + + $title + + + + + + + + + + + + + + +
+ + + +
+
diff --git a/doc/img/e.png b/doc/img/e.png new file mode 100644 index 0000000000000000000000000000000000000000..d42aeb420098578b19a3eab3d6d1e6e73e3277bc GIT binary patch literal 30052 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 EKVH2_NB{r; literal 0 HcmV?d00001 diff --git a/doc/img/edoxy.css b/doc/img/edoxy.css new file mode 100644 index 0000000..311ca23 --- /dev/null +++ b/doc/img/edoxy.css @@ -0,0 +1,486 @@ +/* + * This file contain a custom doxygen style to match e.org graphics + */ + + + +/* BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +}*/ +BODY, TD { + font-size: 12px; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { + font-weight: bold +} +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navpath { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { + text-decoration: none; + background-color: #6666cc; + color: #ffffff +} +A.el { + text-decoration: none; + font-weight: bold +} +A.elRef { + font-weight: bold +} +A.code:link { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.code:visited { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.codeRef:link { + font-weight: normal; + color: #0000FF +} +A.codeRef:visited { + font-weight: normal; + color: #0000FF +} +A:hover, A:visited:hover { + text-decoration: none; + /* background-color: #f2f2ff; */ + color: #000055; +} +A.anchor { + color: #000; +} +DL.el { + margin-left: -1cm +} +.fragment { + font-family: monospace, fixed; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { + margin-left: 16px; + font-style: italic; + font-size: 90% +} +/*BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +}*/ +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { + text-align: center; +} +IMG.formulaDsp { +} +IMG.formulaInl { + vertical-align: middle; +} +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +SPAN.vhdldigit { color: #ff00ff } +SPAN.vhdlchar { color: #000000 } +SPAN.vhdlkeyword { color: #700070 } +SPAN.vhdllogic { color: #ff0000 } + +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { + color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { + font-size: 75%; +} +a { + color: #1A41A8; +} +a:visited { + color: #2A3798; +} +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { + background: #e8eef2; + font-weight: bold; +} +HR { + height: 1px; + border: none; + border-top: 1px solid black; +} + +/* Style for detailed member documentation */ +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; + margin-left: 3px; +} +.memnav { + background-color: #eeeeee; + border: 1px solid #dddddd; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +.memitem { + padding: 4px; + background-color: #eeeeee; + border-width: 1px; + border-style: solid; + border-color: #dddddd; + -moz-border-radius: 4px 4px 4px 4px; +} +.memname { + white-space: nowrap; + font-weight: bold; + color: #ffffff; +} +.memdoc{ + padding-left: 10px; +} +.memproto { + background-color: #111111; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #000000; + font-weight: bold; + -moz-border-radius: 4px 4px 4px 4px; +} +.paramkey { + text-align: right; + color: #ffffff; +} +.paramtype { + white-space: nowrap; + color: #aaaaaa; +} +.paramname { + color: #ff0000; + font-style: italic; + white-space: nowrap; +} +/* End Styling for detailed member documentation */ + +/* for the tree view */ +.ftvtree { + font-family: sans-serif; + margin:0.5em; +} +/* these are for tree view when used as main index */ +.directory { + font-size: 9pt; + font-weight: bold; +} +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* The following two styles can be used to replace the root node title */ +/* with an image of your choice. Simply uncomment the next two styles, */ +/* specify the name of your image and be sure to set 'height' to the */ +/* proper pixel height of your image. */ + +/* .directory h3.swap { */ +/* height: 61px; */ +/* background-repeat: no-repeat; */ +/* background-image: url("yourimage.gif"); */ +/* } */ +/* .directory h3.swap span { */ +/* display: none; */ +/* } */ + +.directory > h3 { + margin-top: 0; +} +.directory p { + margin: 0px; + white-space: nowrap; +} +.directory div { + display: none; + margin: 0px; +} +.directory img { + vertical-align: -30%; +} +/* these are for tree view when not used as main index */ +.directory-alt { + font-size: 100%; + font-weight: bold; +} +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} +.directory-alt > h3 { + margin-top: 0; +} +.directory-alt p { + margin: 0px; + white-space: nowrap; +} +.directory-alt div { + display: none; + margin: 0px; +} +.directory-alt img { + vertical-align: -30%; +} + diff --git a/doc/img/emotion_ratio.eps b/doc/img/emotion_ratio.eps new file mode 100644 index 0000000..624196b --- /dev/null +++ b/doc/img/emotion_ratio.eps @@ -0,0 +1,4541 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: (ImageMagick) +%%Title: (bla.eps) +%%CreationDate: (2011-08-04T18:14:47-03:00) +%%BoundingBox: -0 -0 566 174 +%%HiResBoundingBox: 0 0 565.663 174 +%%DocumentData: Clean7Bit +%%LanguageLevel: 1 +%%Pages: 1 +%%EndComments + +%%BeginDefaults +%%EndDefaults + +%%BeginProlog +% +% Display a color image. The image is displayed in color on +% Postscript viewers or printers that support color, otherwise +% it is displayed as grayscale. +% +/DirectClassPacket +{ + % + % Get a DirectClass packet. + % + % Parameters: + % red. + % green. + % blue. + % length: number of pixels minus one of this color (optional). + % + currentfile color_packet readhexstring pop pop + compression 0 eq + { + /number_pixels 3 def + } + { + currentfile byte readhexstring pop 0 get + /number_pixels exch 1 add 3 mul def + } ifelse + 0 3 number_pixels 1 sub + { + pixels exch color_packet putinterval + } for + pixels 0 number_pixels getinterval +} bind def + +/DirectClassImage +{ + % + % Display a DirectClass image. + % + systemdict /colorimage known + { + columns rows 8 + [ + columns 0 0 + rows neg 0 rows + ] + { DirectClassPacket } false 3 colorimage + } + { + % + % No colorimage operator; convert to grayscale. + % + columns rows 8 + [ + columns 0 0 + rows neg 0 rows + ] + { GrayDirectClassPacket } image + } ifelse +} bind def + +/GrayDirectClassPacket +{ + % + % Get a DirectClass packet; convert to grayscale. + % + % Parameters: + % red + % green + % blue + % length: number of pixels minus one of this color (optional). + % + currentfile color_packet readhexstring pop pop + color_packet 0 get 0.299 mul + color_packet 1 get 0.587 mul add + color_packet 2 get 0.114 mul add + cvi + /gray_packet exch def + compression 0 eq + { + /number_pixels 1 def + } + { + currentfile byte readhexstring pop 0 get + /number_pixels exch 1 add def + } ifelse + 0 1 number_pixels 1 sub + { + pixels exch gray_packet put + } for + pixels 0 number_pixels getinterval +} bind def + +/GrayPseudoClassPacket +{ + % + % Get a PseudoClass packet; convert to grayscale. + % + % Parameters: + % index: index into the colormap. + % length: number of pixels minus one of this color (optional). + % + currentfile byte readhexstring pop 0 get + /offset exch 3 mul def + /color_packet colormap offset 3 getinterval def + color_packet 0 get 0.299 mul + color_packet 1 get 0.587 mul add + color_packet 2 get 0.114 mul add + cvi + /gray_packet exch def + compression 0 eq + { + /number_pixels 1 def + } + { + currentfile byte readhexstring pop 0 get + /number_pixels exch 1 add def + } ifelse + 0 1 number_pixels 1 sub + { + pixels exch gray_packet put + } for + pixels 0 number_pixels getinterval +} bind def + +/PseudoClassPacket +{ + % + % Get a PseudoClass packet. + % + % Parameters: + % index: index into the colormap. + % length: number of pixels minus one of this color (optional). + % + currentfile byte readhexstring pop 0 get + /offset exch 3 mul def + /color_packet colormap offset 3 getinterval def + compression 0 eq + { + /number_pixels 3 def + } + { + currentfile byte readhexstring pop 0 get + /number_pixels exch 1 add 3 mul def + } ifelse + 0 3 number_pixels 1 sub + { + pixels exch color_packet putinterval + } for + pixels 0 number_pixels getinterval +} bind def + +/PseudoClassImage +{ + % + % Display a PseudoClass image. + % + % Parameters: + % class: 0-PseudoClass or 1-Grayscale. + % + currentfile buffer readline pop + token pop /class exch def pop + class 0 gt + { + currentfile buffer readline pop + token pop /depth exch def pop + /grays columns 8 add depth sub depth mul 8 idiv string def + columns rows depth + [ + columns 0 0 + rows neg 0 rows + ] + { currentfile grays readhexstring pop } image + } + { + % + % Parameters: + % colors: number of colors in the colormap. + % colormap: red, green, blue color packets. + % + currentfile buffer readline pop + token pop /colors exch def pop + /colors colors 3 mul def + /colormap colors string def + currentfile colormap readhexstring pop pop + systemdict /colorimage known + { + columns rows 8 + [ + columns 0 0 + rows neg 0 rows + ] + { PseudoClassPacket } false 3 colorimage + } + { + % + % No colorimage operator; convert to grayscale. + % + columns rows 8 + [ + columns 0 0 + rows neg 0 rows + ] + { GrayPseudoClassPacket } image + } ifelse + } ifelse +} bind def + +/DisplayImage +{ + % + % Display a DirectClass or PseudoClass image. + % + % Parameters: + % x & y translation. + % x & y scale. + % label pointsize. + % image label. + % image columns & rows. + % class: 0-DirectClass or 1-PseudoClass. + % compression: 0-none or 1-RunlengthEncoded. + % hex color packets. + % + gsave + /buffer 512 string def + /byte 1 string def + /color_packet 3 string def + /pixels 768 string def + + currentfile buffer readline pop + token pop /x exch def + token pop /y exch def pop + x y translate + currentfile buffer readline pop + token pop /x exch def + token pop /y exch def pop + currentfile buffer readline pop + token pop /pointsize exch def pop + /Times-Roman findfont pointsize scalefont setfont + x y scale + currentfile buffer readline pop + token pop /columns exch def + token pop /rows exch def pop + currentfile buffer readline pop + token pop /class exch def pop + currentfile buffer readline pop + token pop /compression exch def pop + class 0 gt { PseudoClassImage } { DirectClassImage } ifelse +} bind def +%%EndProlog +%%Page: 1 1 +%%PageBoundingBox: 0 0 566 174 +userdict begin +DisplayImage +0 0 +565.663 173.619 +12 +707 217 +1 +1 +1 +8 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFF +FFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF0000000000 +00000000FFFFFFFFFFFF0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000FFFFFFFFFF +000000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF00000000000000 +00FFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF00060B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B05FFFFFFFFFFFFFFFFFFFF00 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFF +FFFFFFFF0000000000000000FFFFFFFFFFFF000000000000000000FFFFFFFFFFFF000000 +0000081B607F7F7F7F7F7F471B1B1B1B1B1B4A7F7F7F7F7F7F5D1B1B1B1B1B1B317F7F7F +7F7F7F731B1B1B1B1B1B1B7F7F7F7F7F7F7F251B1B1B1B1B1B6A7F7F7F7F7F7F3E1B1B1B +1B1B1B547F7F7F7F7F7F541B1B1B1B1B1B3E7F7F7F7F7F7F6A1B1B1B1B1B1B257F7F7F7F +7F7F7F1B1B1B1B1B1B1B737F7F7F7F7F7F341B1B1B1B1B1B5D7F7F7F7F7F7F4A1B1B1B1B +1B1B477F7F7F7F7F7F601B1B1B1B1B1B210AFFFFFFFFFF000000000000000000FFFFFFFF +FFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF000000000000 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0005868686 +868686868686868686868686868686868686868686868686868686868686868686868686 +868686868686868686868686868686868686868686868686868686868686868686868686 +868686868686868686868686868686868686868686868686868686868686868686868686 +868686868686868686868686868686868686868686868686868686868686868686868686 +868686868686868686868600FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +3ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFF +FFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFF +FFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFF +FF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFF +FFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC92 +10FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFF +FFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFF +FFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF0000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +3ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC07 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFF +FFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFF +FFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3AA988673788B9EB0CACCCCCCCC9210FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBC9EA6C3CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFF +FF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC763939393939A7CCCC +CCCCCC773939393939CACCCCCCCCCCCCCCCCCCCC57393939393939393939393A424E5964 +6F81A6C9CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A39393939393939 +393939393939393939393939393939393939ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCAE71350400000000000000000E4884BECC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC845F5F86CCCCCCCC +CCCCCCCCCCCCCCCCCCCC825F5F8CCCCCCC675F5FB4CCCCCCCCCC975F5F5F5F5F606A7E92 +B8CCCCCCCCCCCCCCCCCCCCCCCCCCCC6F5F5F5F5F5F5F5F5F5F5F5F5F5F6BCCCCCCCCCCCC +CCCCCCCCCA7E1900000001309DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCA140000000012C9CCCCCCCCCC560000000000CACCCCCC +CCCCCCCCCCCCCC2A000000000000000000000000000000000000062A5287C7CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC000000000000000000000000000000000000000000 +00000000009FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA737000000000000000000000000 +000000055C8A10FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000027CCCCCCCCCCCCCCCCCCCCCCCCCCCC1F0000 +74CCCCCC0E00009ECCCCCCCCCC6800000000000000000002337AC7CCCCCCCCCCCCCCCCCC +CCCC1E0000000000000000000000000015CCCCCCCCCCCCCCCCCCBD2A0000000000000000 +56CBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9000000000005ECCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000000 +0000000000000000000000000000000000105CADCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00000000000000000000000000000000000000000000000000009FCCCCCCCCCCCCCC +CCCCCCCCCCCCCCB94E020000000000000000000000000000000000000B09FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC92000003C5CCCCCCCCCCCCCCCCCCCCCCCCBF010000A0CCCCCC0E00009ECCCCCCCCCC +6800000000000000000000000026A8CCCCCCCCCCCCCCCCCCCC1E00000000000000000000 +00000015CCCCCCCCCCCCCCCCBC250000000000000000000050CBCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC430000000000ABCCCCCCCCCCCC +560000000000CACCCCCCCCCCCCCCCCCCCC2A000000000000000000000000000000000000 +0000000000000043BBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0000000000000000000000 +0000000000000000000000000000009FCCCCCCCCCCCCCCCCCCCCCCCCCCAA160000000000 +0000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBD0000009ECCCCCCCCCCCC +CCCCCCCCCCCC95000005C6CCCCCC0E00009ECCCCCCCCCC68000000000000000000000000 +00058CCCCCCCCCCCCCCCCCCC1E0000000000000000000000000015CCCCCCCCCCCCCCCC3A +00000000000000000000000073CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCBD05000000002DCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCC +CCCCCCCC2A0000000003121212121212120900000000000000000000000000128CCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC000000000000000000000000000000000000000000000000 +00009FCCCCCCCCCCCCCCCCCCCCCCCC9D0E000000000000001E628A9EB2AC98824D0E0000 +00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC1D000072CCCCCCCCCCCCCCCCCCCCCCCC6A00002ACCCCCC +CC0E00009ECCCCCCCCCC6800000000000000000000000000000AA8CCCCCCCCCCCCCCCC1E +0000000000000000000000000015CCCCCCCCCCCCCC86000000001061867D4E030000000A +B6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFF +FFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC75000000 +00007ACCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCC +CCCCCCCCCCCABFB28A5E310400000000000000005ACCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +0000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9B0700000000000032A5CCCCCCCCCCCCCCCCCCC9861300000000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +49000047CCCCCCCCCCCCCCCCCCCCCCCC3E000056CCCCCCCC0E00009ECCCCCCCCCC680000 +40BFBFBFBDA88F4E09000000001AC5CCCCCCCCCCCCCC1E000074A6A6A6A6A6A6A6A6A6A6 +AACCCCCCCCCCCCC4130000003EBFCCCCCCCCAA1900000046CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC280000000008C1CCCCCCCCCCCCCC560000 +000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCB866 +13000000000000006FCCCCCCCCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBE160000000000067CCBCCCCCC +CCCCCCCCCCCCCCCCCCBF4A000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7500001CCCCCCCCCCCCCCCCCCC +CCCCCC13000082CCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCBD3C000000 +0074CCCCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7D0000002EC6 +CCCCCCCCCCCCAB0E000002B6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003DCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCA700000000004ACCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCC +CC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC75C0000000000000189CCCCCC +CCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC4100000000000693CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB5200 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCA1000000BDCCCCCCCCCCCCCCCCCCCCB4000000AECCCCCCCC0E00 +009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCB5300000016C7CCCCCCCCCCCC1E00008E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC29000003ADCCCCCCCCCCCCCCCC7600000067CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFF +FFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF002ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC5A000000000098CC +CCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC8E0B000000000008B8CCCCCCCCCCCCCCCCCCCCCC00000000 +0052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7E000000 +00000290CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB3400FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC70500 +0092CCCCCCCCCCCCCCCCCCCC8900000ECBCCCCCCCC0E00009ECCCCCCCCCC68000044CCCC +CCCCCCCCCCCCCCC72A00000084CCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCA200000052CCCCCCCCCCCCCCCCCCC81D000017CBCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8E595974CCCCCCCCCCCCCCCCCCCC +CCCCCCCC80595985CCCCCC6A5959AACCCCCCCCCC9D5959595959595E687286ADCACCCCCC +CCCCCCCCCCCCCCCCCC72595959595959595959595959595DCCCCCCCCCCCCCCCCCCCCB170 +361B080A1E3D78B9CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0013CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCC811000000001ACBCCCCCCCCCCCCCCCC560000000000 +CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +8F01000000000059CCCCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA1D000000000056CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC8B02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC2B000067CCCCCCCCCCCCCCCCCCCC5E +000039CCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCC9E00000048 +CCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000000ABCCCCCCCCCC +CCCCCCCCCC6F000000A6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9A000004BBCCCCCCCCCCCCCCCCCCCCCCCCC60E00008ACCCCCC1D00 +008FCCCCCCCCCC7700000000000000000000000A4899CCCCCCCCCCCCCCCCCCCC2D000000 +0000000000000000000006CCCCCCCCCCCCCCCCB950020000000000000000065FC2CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0001BACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC8C000000000067CCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A00 +00000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000000000006B8CCCCCCCC +CCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC8C000000000016C2CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC920BFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC5700003CCCCCCCCCCCCCCCCCCCCC32000064CCCCCCCCCC0E00009ECC +CCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCC2A000010CACCCCCCCCCC1E00008ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC3300002ACCCCCCCCCCCCCCCCCCCCCCB602000074CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFF +FFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1D0000 +72CCCCCCCCCCCCCCCCCCCCCCCC88000010C8CCCCCC1D00008FCCCCCCCCCC770000000000 +00000000000000000030AFCCCCCCCCCCCCCCCC2D0000000000000000000000000006CCCC +CCCCCCCCCCAC17000000093B514E360500000026B9CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF000070CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3E0000000002B4CCCCCCCCCC +CCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCA1A00000000005BCCCCCCCCCCCCCCCCCCCC000000000052CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3200000000007ACC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC83000011CC +CCCCCCCCCCCCCCCCCA09000090CCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCC +CCCCCCCCCCCC78000000A2CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6 +0600006DCCCCCCCCCCCCCCCCCCCCCCCC2D000042CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6A000026CCCCCCCCCCCCCCCCCCCCCCCC +3B00005ACCCCCCCC1D00008FCCCCCCCCCC77000033C6C6C6C5BBAF8E61170000000897CC +CCCCCCCCCCCC2D000073B9B9B9B9B9B9B9B9B9B9BACCCCCCCCCCCCB21000000B73C4CCCC +CCCCBE620500001EC1CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000023CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCBA030000000037CCCCCCCCCCCCCCCCCCCC560000000000CACCCC +CCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC75 +00000000001ACCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCB0000000000008C1CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAF000000B2CCCCCCCCCCCCCCCCA8000000BB +CCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCAE0000007ACCCC +CCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9E0000009ACCCCCCCCCCCCCCCCCC +CCCCCC5A000012CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCB6020000A6CCCCCCCCCCCCCCCCCCCCB7020000A7CCCCCCCC1D00008FCC +CCCCCCCC77000035CCCCCCCCCCCCCCCCCA7C0800000DACCCCCCCCCCCCC2D00007FCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCC82C000011AACCCCCCCCCCCCCCCC9707000048CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000A3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC710000 +00000085CCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A00000000 +29CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC30D0000000000B5CCCCCCCCCCCC +CCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC8000000000004BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC0F000087CCCCCCCCCCCCCCCC7D00001ACCCCCCCCCCCC0E00009ECCCCCCCC +CC68000044CCCCCCCCCCCCCCCCCCCCCCCC1600005DCCCCCCCCCC1E00008ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC81000002C4CCCCCCCCCCCCCCCCCCCCCCCC86000000C2CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A000059CC +CCCCCCCCCCCCCCCCCC6D000029CCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCC +CCCCCCCCCCA206000039CCCCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +770000019ACCCCCCCCCCCCCCCCCCCC7E0000009ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF00000056CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC23000000000DC6CCCCCCCCCCCCCCCCCC +CC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC3F000000000082CCCCCCCCCCCCCCCCCC000000000052CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC51000000000089CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A00005CCCCCCC +CCCCCCCCCC52000046CCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCC +CCCCCCCC3C000041CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000020 +CCCCCCCCCCCCCCCCCCCCCCCCCCAB000000A6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC88000010C8CCCCCCCCCCCCCCCCCC20000076 +CCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCC76000000A2CCCC +CCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB1E00004ECCCCCCCCCCCCCCCCCC +CCCCCB2C00003FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000EC7CCCCCCCCCCCCCC +CCCCCCCCCCCCA2000000000055CCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCC +CCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6D0000 +0000004FCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC220000000000B2CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000031CCCCCCCCCCCCCCCC26000072CCCCCCCC +CCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC55000024CCCCCCCCCC +1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4A000037CCCCCCCCCCCCCCCCCCCCCCCCCC +C30000008BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCC70F00008BCCCCCCCCCCCCCCCC9F000006BECCCCCCCCCC1D00008FCCCCCCCC +CC77000035CCCCCCCCCCCCCCCCCCCCCCC71400005BCCCCCCCCCC2D00007FCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9E000000A4CCCCCCCCCCCCCCCCCCCCCCCC81000002BECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000000089CCCCCCCCCCCCCCCCCCCCCCCCCC550000000000A2 +CCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9B00000000002ECCCCCCCCCCCCCCCCCC +000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC30100 +0000000ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC92000008CACCCCCCCCCCCCC40300009ECCCCCCCCCCCC0E00009ECCCCCCCCCC6800 +0044CCCCCCCCCCCCCCCCCCCCCCCC6E00000ECCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC3000004ECCCCCCCCCCCCCCCCCCCCCCCCCCCC0E000071CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC5800003ECCCCCC +CCCCCCCCCC52000046CCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCC +CCCCCCCC54000028CCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6C000018 +CCCCCCCCCCCCCCCCCCCCCCCCCCC10100008FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +00003CCCCCCCCCCCCCCCCCCCCCCCCCC60E0000000024CCCCCCCCCCCCCCCCCCCCCCCC5600 +00000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCBB000000000021CCCCCCCCCCCCCCCCCC00000000001739393939393939 +39393939393939393939393995CCCCCCCCCCCCCCB200000000002FCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBE000000A7CCCCCCCCCC +CC9C000004C6CCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCC +CC82000006CCCCCCCCCC1E00004766666666666666666666A4CCCCCCCC26000064CCCCCC +CCCCCCCCCCCCCCCCCCCCCC23000066CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA6000003BACCCCCCCCCCCCC50C000094CCCCCCCC +CCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCCCC80000002CACCCCCCCC +2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC40000042CCCCCCCCCCCCCCCCCCCCCCCCCC +CC1F000062CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000002B9CCCCCCCCCCCCCCCCCC +CCCC87000000000072CCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCC +CCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC90000000000 +12CCCCCCCCCCCCCCCCCC000000000000000000000000000000000000000000000000007F +CCCCCCCCCCCCCCA300000000003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC1D00007CCCCCCCCCCCCC71000029CCCCCCCCCCCCCC0E +00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC8B000000CBCCCCCCCC1E0000 +00000000000000000000007BCCCCCCCC1F00006DCCCCCCCCCCCCCCCCCCCCCCCCCCCC2C00 +005ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC28000072CCCCCCCCCCCC84000017CACCCCCCCCCCCC1D00008FCCCCCCCCCC7700 +0035CCCCCCCCCCCCCCCCCCCCCCCC9A000000BECCCCCCCC2D000000000000000000000000 +006CCCCCCCCC2F00005DCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A00004FCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF00000000006ECCCCCCCCCCCCCCCCCCCCCC3A0000000004BBCCCCCCCC +CCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0A0000000004CCCCCCCCCCCCCCCCCC000000 +000000000000000000000000000000000000000000007FCCCCCCCCCCCCCC940000000000 +4ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC49000051CCCCCCCCCCCC46000055CCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CC +CCCCCCCCCCCCCCCCCCCCCC94000000C4CCCCCCCC1E000000000000000000000000007BCC +CCCCCC18000074CCCCCCCCCCCCCCCCCCCCCCCCCCCC33000055CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC76000024CCCCCCCCCC +CC37000063CCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCC +CCA9000000B0CCCCCCCC2D000000000000000000000000006CCCCCCCCC2200006ACCCCCC +CCCCCCCCCCCCCCCCCCCCCC46000041CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000 +22CCCCCCCCCCCCCCCCCCCCB6020000000042CCCCCCCCCCCCCCCCCCCCCCCCCC5600000000 +00CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC160000000000C2CCCCCCCCCCCCCCCC00000000000000000000000000000000 +0000000000000000007FCCCCCCCCCCCCCC85000000000056CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC75000026CCCCCCCCCCCC1A00 +0080CCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC9C00 +0000BDCCCCCCCC1E000000000000000000000000007BCCCCCCCC1200007ACCCCCCCCCCCC +CCCCCCCCCCCCCCCC3A00004DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCBE060000A4CCCCCCCCB5020001B0CCCCCCCCCCCCCC1D +00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCCCCAA000000AECCCCCCCC2D0000 +2B464646464646464646468ECCCCCCCC2000006CCCCCCCCCCCCCCCCCCCCCCCCCCCCC4A00 +003DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000A2CCCCCCCCCCCCCCCCCC6C00 +000000008FCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A +0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC160000000000C4CC +CCCCCCCCCCCCCC000000000000000000000000000000000000000000000000007FCCCCCC +CCCCCCCC83000000000056CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCA1000002C4CCCCCCCCBB000000ACCCCCCCCCCCCCCC0E00009E +CCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC9E000000BACCCCCCCC1E0000000000 +00000000000000007BCCCCCCCC0E00007ECCCCCCCCCCCCCCCCCCCCCCCCCCCC3D000049CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC46000057CCCCCCCC69000032CCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CC +CCCCCCCCCCCCCCCCCCCCCC9C000000BCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC2C000060CCCCCCCCCCCCCCCCCCCCCCCCCCCC3E00004CCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF00000000000054CCCCCCCCCCCCCCCCCC1F0000000014CACCCCCCCCCCCCCCCC +CCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC090000000007CCCCCCCCCCCCCCCCCC000000000052 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9200000000004ACCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC706 +00009CCCCCCCCC9000000CCBCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCC +CCCCCCCCCCCCCCCC97000000C2CCCCCCCC1E00006F9F9F9F9F9F9F9F9F9F9FBACCCCCCCC +14000078CCCCCCCCCCCCCCCCCCCCCCCCCCCC36000051CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9400000FC7CCCCCC1D0000 +80CCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCCCC8500 +0001C9CCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A00004ACCCCCCCCCCCC +CCCCCCCCCCCCCCCC2700005CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000E000000000EC6 +CCCCCCCCCCCCCC9E00000000005ECCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACC +CCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCC8000000000016CCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCA200000000003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC2C000071CCCCCCCC65000036CCCC +CCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC8E000000C9 +CCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1B000071CCCCCCCCCCCCCCCCCC +CCCCCCCCCC30000059CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCA1700008ACCCC9B00000AC3CCCCCCCCCCCCCCCC1D00008F +CCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCCCC5A000022CCCCCCCCCC2D00007FCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC60000022CCCCCCCCCCCCCCCCCCCCCCCCCCC704000084CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0026000000000087CCCCCCCCCCCCCC510000000000 +ADCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A000000 +0029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBB000000000026CCCCCCCCCC +CCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCB1000000000032CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC58000046CCCCCCCC3A000062CCCCCCCCCCCCCCCC0E00009ECCCCCC +CCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC86000004CCCCCCCCCC1E00008ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC2200006ACCCCCCCCCCCCCCCCCCCCCCCCCCCC29000061CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +6300003DCCCC4E00004FCCCCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCC +CCCCCCCCCCCCCCCA1E000054CCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +91000001B3CCCCCCCCCCCCCCCCCCCCCCCC92000000B6CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003B09000000003ACCCCCCCCCCCCC50B000000002ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC9A000000000035CCCCCCCCCCCCCCCCCC000000000052CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1000000000012CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8400001A +CCCCCCCC0E00008ECCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCC +CCCCCCCCCC7700000BCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC290000 +5ACCCCCCCCCCCCCCCCCCCCCCCCCCCC1A00006ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB1010003BAC30A00009DCCCCCC +CCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCC8900000093CC +CCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC40E000063CCCCCCCCCCCCCCCC +CCCCCCCC4100002BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E4C0000000002B7CCCC +CCCCCC8200000000007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCC +CCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6C00 +0000000057CCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC1B0000000000B6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB0000000BCCCCCAF000000BACCCCCCCCCC +CCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC5F00001ACCCCCCCC +CC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3B000043CCCCCCCCCCCCCCCCCCCCCCCC +CCCA0400007DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC330000708000001ECCCCCCCCCCCCCCCCCCCC1D00008FCCCCCC +CCCC77000035CCCCCCCCCCCCCCCCCCCCB61200002ACCCCCCCCCCCC2D00007FCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC60000008B1CCCCCCCCCCCCCCCCCCCC9A00000086CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF003E9A00000000006DCCCCCCCCCC360000000008C2CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3F00000000008ACCCCCCCCCCCCCCCC +CC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4A +00000000008DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC0F000091CCCC84000019CCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68 +000044CCCCCCCCCCCCCCCCCCCCCCCC46000036CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC5700002CCCCCCCCCCCCCCCCCCCCCCCCCCCB800000098CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8200 +00233300006CCCCCCCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCC +CCCCA1190000049BCCCCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBB14 +000026BECCCCCCCCCCCCCCCCB11600002BC9CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +3ECC1D0000000020CCCCCCCCB301000000004CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC56 +0000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCC40D0000000000BBCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7A000000000053CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A000066CCCC +59000045CCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCC +CCCC2A000052CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7200000FCCCC +CCCCCCCCCCCCCCCCCCCCCC9B000000B4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC40B0000000002B7CCCCCCCCCCCCCC +CCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCB4873B0100000081CCCCCCCCCCCC +CC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC970200001F9DCCCCCCCCCCCC8D14 +000009AECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC07 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC6A00000000009FCCCCCC67 +00000000009ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCC +CCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC760000000000 +22CCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCAA00000000000CC5CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6600003ACCCC2D000071CCCCCCCCCCCCCCCCCC +0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCC20300006ECCCCCCCCCC1E00 +008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8E000000B1CCCCCCCCCCCCCCCCCCCCCCCC7000 +0005CACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFF +FFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC51000000003BCCCCCCCCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77 +0000081F1F1F1E150900000000001795CCCCCCCCCCCCCCCC2D00000B1212121212121212 +1212129ECCCCCCCCCCCC8A060000002B627B795E220000000F9ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF003ECCB6020000000052CCCCCB1B000000001CCBCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA1D000000000061CCCCCCCCCCCCCCCCCCCC0000 +00000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC260000 +00000082CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC92000010CCC80600009CCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044 +CCCCCCCCCCCCCCCCCCCCCC900000008ECCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCB200000085CCCCCCCCCCCCCCCCCCCCCCCC44000028CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9F000000 +008ACCCCCCCCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC7700000000000000000000000027 +76C2CCCCCCCCCCCCCCCCCC2D000000000000000000000000000099CCCCCCCCCCCCCCA128 +0000000000000000000036AECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC +3A000000000DC6CC9A000000000069CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC56000000 +0000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC6A000000000008BBCCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8100000000001EC6CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC920CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBE000000B1A3000003 +C5CCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCC5100 +0003C0CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1800004ECCCCCCCC +CCCCCCCCCCCCCCCA1200005ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC45323239C7CCCCCCCCCCCCCCCCCCCCCC +4932329ECCCCCCCCCC8D323232323232384551668DB5CCCCCCCCCCCCCCCCCCCCCCCC5532 +32323232323232323232323232A6CCCCCCCCCCCCCCCCCB87430A00000000104B94CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC88000000000086CC4C00000000 +02B5CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC +2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC940200000000005BCCCCCC +CCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCC714000000000062CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8E02 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1E00008678000027CCCCCCCCCCCCCCCCCCCC0E0000 +9ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCBE0800002FCCCCCCCCCCCC1E00008ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4B00000CC6CCCCCCCCCCCCCCCCCCCC940000008CCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFF +FFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCBBEAEAFC0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF003ECCCCC70F0000000038C2090000000039CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC940E000000000008B9CCCCCCCCCCCCCCCCCCCCCC0000000000 +52CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7000000000 +00049ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3E00FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC4A00005A4D000052CCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCC +CCCCCCCCCCCCCC6600000069CCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC7E00000086CCCCCCCCCCCCCCCCCCCC4A000002BECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC5800 +0000000267000000000086CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CA +CCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9620100 +000000000189CCCCCCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA3100000000000BA1CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC630000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7600002F2100007ECCCCCC +CCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCC9C03000002B0CC +CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC008000022CACCCCCCCCCC +CCCCCCAE0300003BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCA6000000000002000000000EC6CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000 +000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCBC6C180000000000000070CCCCCCCCCCCCCCCC +CCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCB40E00000000000D8FCCCCCCCCCCCCCCCCCCCCCCCCCCC65D000000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCA2000006010000AACCCCCCCCCCCCCCCCCCCC0E00009ECCCC +CCCCCC68000044CCCCCCCCCCCCCCCC98120000004ACCCCCCCCCCCCCC1E00008ECCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC5000000078CCCCCCCCCCCCCCCC3E0000008ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFF +FF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF003ECCCCCCCC2800000000000000000056CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCC6 +B89164370600000000000000005ACCCCCCCCCCCCCCCCCCCCCCCCCCCC000000000052CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8A0200000000 +000044B6CCCCCCCCCCCCCCCCCCCC991F00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7 +06000000000BCACCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCC +AA580200000002ADCCCCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +A50000000596CCCCCCCCCCCC6100000016CACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCC76000000 +000000000000A4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCC +CCCCCCCCCCCCCC2A0000000005191919191919180F040000000000000000000000000F88 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC000000000002060606060606060606060606060606 +06060606063ECCCCCCCCCCCCCCCCCCCCCCCC89060000000000000232759EB2C5BFAB9660 +1E000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC2C0000000035CCCCCCCCCCCCCC +CCCCCCCC0E00009ECCCCCCCCCC6800001A4C4C4C4A351C0000000000006BCCCCCCCCCCCC +CCCC1E0000283939393939393939393939B2CCCCCCCCCCCC43000000086DC7CCCCB94900 +0000007ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCBE060000000000000026CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000000 +00000000000000000000000000000000000000003BB8CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC000000000000000000000000000000000000000000000000000039CCCCCCCCCCCCCC +CCCCCCCCCCCC990C00000000000000000000000000000000000000000000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC580000000061CCCCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC +68000000000000000000000000000048CCCCCCCCCCCCCCCCCC1E00000000000000000000 +00000000A8CCCCCCCCCCCCB70B0000000006261D020000000031CBCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +003ECCCCCCCCCC460000000000000073CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +560000000000CACCCCCCCCCCCCCCCCCCCC2A000000000000000000000000000000000000 +000000000C54A4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0000000000000000000000 +00000000000000000000000000000039CCCCCCCCCCCCCCCCCCCCCCCCCCCCAA3600000000 +0000000000000000000000000000000407FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC840000 +00008DCCCCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000000000000000000000000 +0055C6CCCCCCCCCCCCCCCCCC1E0000000000000000000000000000A8CCCCCCCCCCCCCC7E +00000000000000000000000CABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCC940000000000 +0005BDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCC +CCCCCCCC2A00000000000000000000000000000000000003254C83C5CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC000000000000000000000000000000000000000000000000 +000039CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9325000000000000000000000000000000 +01478010FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB000000000B8CCCCCCCCCCCCCCCCCCCC +CC0E00009ECCCCCCCCCC6800000000000000000000001B90CCCCCCCCCCCCCCCCCCCCCC1E +0000000000000000000000000000A8CCCCCCCCCCCCCCCC750000000000000000000EA2CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFF +FFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCA3E32323232325ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC733232323232CACCCCCCCCCCCCCCCCCCCC523232323232323232 +3232333B47525E6A7BA2C6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC33 +323232323232323232323232323232323232323232323232325ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCA9A5E22000000000000000000043571AECC9210FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC10000017CCCCCCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC680000 +000000000A1E325AA0CCCCCCCCCCCCCCCCCCCCCCCCCC1E00000000000000000000000000 +00A8CCCCCCCCCCCCCCCCCC871900000000000032A8CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB497 +85726065788A9DC1CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7 +7E53323B5C96CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC92 +10FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFF +FFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFF +FFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00C6C6 +C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +C6C6C6C6C6C6C6C6C6C6C6C60700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +3ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF01030303030303030303030303030303 +030303030303030303030303030303030303030303030303030303030303030303030303 +030303030303030303030303030303030303030303030303030303030303030303030303 +030303030303030303030303030303030303030303030303030303030303030303030303 +030303030303030303030303030303030303030303030303030303030303030303030301 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFF +FFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFF +FFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFF +FF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFF +FFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC92 +10FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFF +FFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFF +FFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000 +FFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFF00 +00000000000000FFFFFFFFFF001715151515151533757575757575631515151515151F75 +757575757575191515151515156A7575757575752E151515151515517575757575754315 +15151515153D75757575757557151515151515287575757575756F151515151515157275 +7575757575251515151515155D75757575757539151515151515467575757575754E1515 +1515151530757575757575671515151515151B757575757575751B0F010000000000FFFF +FFFFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF00000000 +00000000FFFFFFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0006ACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +ACACACACACACACACACACACACACACACACACACACACACAC00FFFFFFFFFFFFFFFFFFFF000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFF00000000000000 +00FFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFF00 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000FFFFFFFFFFFF0000000000000000FF +FFFFFFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF000000 +000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00060B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B05FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000FF00000000 +000000FFFFFFFF00000000000000000000000000000000000000FFFF00000000000000FF +FF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +000000000000000000000000000000000000FF0000000000000000FFFFFF000000000000 +00000000000000000000000000000000000000000000FFFF0000FFFFFFFFFF000000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF0000FFFFFFFF0000 +00FFFFFFFFFF0000FFFFFF000000FFFFFF0000FFFFFFFFFFFFFFFFFFFF000000FFFFFFFF +00000000FFFFFF0000FFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF0000FFFFFF0000 +00FFFFFF0000FFFFFFFFFFFFFFFFFFFF000000FFFFFF00000000FFFFFFFFFFFFFFFF0000 +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FF +FFFFFFFFFFFFFFFF000000FFFFFFFFFF0000FFFFFF000000FFFFFF0000FFFFFFFFFFFFFF +FFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF0000FFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFFFF000000FFFF +FFFFFF0000000000000000FFFFFF0000000000000000FFFFFFFF000000FFFFFF000000FF +FFFFFFFFFFFFFFFF00000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF00000000000000FFFFFFFF000000FFFFFFFFFF00000000000000FFFFFF +FF0000000000000000FFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF0000000000 +0000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000 +00FFFFFFFF000000FFFFFFFFFF0000000000000000FFFFFF0000FFFFFFFFFFFFFFFFFFFF +000000FFFFFF000000FFFFFFFFFFFFFFFFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000000000000000FF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF000000FFFFFFFFFF +0000FFFFFF000000FFFFFF0000FFFFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFF +FFFFFFFFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000 +00FFFF0000FF0000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000 +FF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF00FFFFFFFFFF000000FFFFFFFF000000FFFFFFFFFF0000FFFFFFFF000000FFFF0000 +FFFFFFFFFFFFFFFFFFFF000000FFFFFFFF000000FFFFFFFFFF00FFFF0000FFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFF0000FF00000000000000 +00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF000000FFFFFFFF +FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000FFFF +FFFF000000FFFFFFFFFF0000FFFFFFFF000000FFFF0000000000000000FFFFFFFF000000 +FFFFFFFF000000000000000000FFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF000000FFFFFFFFFFFF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFF000000FFFFFFFFFF0000FF +FFFFFFFF000000FF0000000000000000FFFFFFFF000000FFFFFFFFFF0000000000000000 +FFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF +0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF0000 +00FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFF000000FFFF000000FFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000000000000000FFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +000000000000FFFF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFF0000FF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF +000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF000000FFFFFFFFFFFF000000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000 +FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF +FFFFFFFFFF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF000000 +0000000000FF0000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF0000000000000000FF00000000000000 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF +FFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +end +%%PageTrailer +%%Trailer +%%EOF diff --git a/doc/img/emotion_ratio.png b/doc/img/emotion_ratio.png new file mode 100644 index 0000000000000000000000000000000000000000..4ae37fde7647ecd03923e060b2603e1de198b7a0 GIT binary patch literal 12950 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 GLK6Ub>Mc;VkfoEM{Qf z76xHPhFNnYfP(BLp1!W^H+WcuRXD>A=l%i;Wq7(chG?8W+i%Esz<`6f_y7NWHH!5o z63R1{^0cb0vMSkFaE_%x<+7O{*?Xs&Ff%xKT5jO&GtAqcqoa~}b>qg&H07ky z617wnX2HUfTT*8{kPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOZ8 z6%`IG`XD&~00I3;L_t(o!^Kz8j>8}fODg_+AF{uksuh}hxC0rJP`W$mkkHl^jB%XM z>f`Y+`Dtd>`gxwMmr`2KIk$cshdiH8N#}XW6$o}5WA?p%5)sKc%eHO9fR!#HlFUqU z&XQ6Z1~3DUmCHm#rjx?$lu|lm24QA+Eh4g2CJ}X<;QbGo;J_$CohD|s1Tu}z3KIrH zRtpQ8-Z|UyQP4caCB~&Z3QG0mMzcQLYIcQ!(sFW-xf9knF@|(?iY~XAOhHzd%#8OD2m>x}XSSsVf@;^obfpX48<@ZgFF$M4@xtjbM#B=Ojp!9yfFNKXj22K7STvD?00000NkvXXu0mjfB76)l literal 0 HcmV?d00001 diff --git a/doc/img/header_menu_current_background.png b/doc/img/header_menu_current_background.png new file mode 100644 index 0000000000000000000000000000000000000000..de97c9268e4ac68310c8b92d6ab6bd8a245611da GIT binary patch literal 1200 zcmV;h1W)^kP)002J-1^@s6XaB>y00001b5ch_0Itp) z=>Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3Fc5TrKj#zpOzs?z2=A0p@aw&u*pMn|G)ug+?Vh;0+zHe5dVLoF=!DBW&zJ?E zp99|S_j0@4%Io#|xG+sqdB5NP{rn5Cj%O+78UIn|DpKcsK9>`B2V6JsOB3oD&r;4a z{-e%Sw9ela{A&{jdu5*U-Tgr1~ zQc-ZvZCmQQrCnTG+COg8zWQ3Lv1sjNIKQPlR|Xsq_}(oT0MbDS91lPg3>xeBFKokrh3I+f~!N36>5GNtP zFb=56FWNP#oK=?bNEQ~!rtXW9X1GX=k~FL`OjOeF$R)LGB-wAZi(5xddgID^{pUl5 z$!2zVWE!iC5c%CAFL=jfl{TW1M$7Wjcr9z}SyPKmlC20r0B}G6Q80PClsJ^eQ9Rdb zuHflIJ5saoBdvW)J5o7`LrQ$sb0li*FS@pt^@$vLe#kJ^<1ntHwKLacEE8!V_VYY{ z^jk0Fa-9o0ILfhhgnDcg*`~%yk#UNgFLkMLQ1xp&>oHLMt>=krgKLZ9aoj&)eVyWk z+VI9yb#%knV zBgOT1iW^1q->g9a$6utrxv^4Ql-s5#yS%xS5>LwpJyaYZ1w-06F426k%%gi2p;YTL zn*Zi$*TU&q<}Gq{z5F%GPa}Dt9$}k233)sorIb>h&nNZ+VE-)`LNtIN1b_p=0f8Pk zSwvore6GJZg3A%uh&UU`%8A$z3ApNcvGym`^9BW5y;mkO7OVYaI#wj=im2;bzSt*w z8j*3rXhhk-tiA%ik?Y6P7yM_$}>d^Cl%aa8a!%A!J=gv)gqCjA%RAmjShY zk&jin$jBj)wrhPzE#o_v^@kLW;DnK~k;Uxogc+{8mlL+=3tKP%4hR4$2Lynj z95C}RO)LJ$<@I?2i7h|tH#%lcU&}tk-(ol0<1_foFDdWsgqjV%=7cRA;M<%KLNw4f z2!R6vT{&RuTk7799C>JZ4;!>{ThW;;ZOYD_SA%VO2ZR&C3B68;Eg1NXEf@e0gaF^` zfS#=57JO;X{zkCF($|*uL^8|wn48N;fkQ7R9I3CpA0+QRH%LYRy5b)R!`g7p731Il O0000002J-1^@s6XaB>y00001b5ch_0Itp) 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 +Vendor: %{?_vendorinfo:%{_vendorinfo}}%{!?_vendorinfo:The Enlightenment Project (http://www.enlightenment.org/)} +Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}} +#BuildSuggests: xorg-x11-devel XFree86-devel libX11-devel libxine1-devel xine-lib-devel +#BuildSuggests: gstreamer-devel gstreamer-plugins-devel gstreamer-plugins-base-devel gstreamer-ffmpeg +BuildRequires: eet-devel evas-devel edje-devel edje-bin +BuildRequires: /usr/bin/xine-config +BuildRoot: %{_tmppath}/%{name}-%{version}-root + +%description +Emotion is a Media Library + +%package devel +Summary: Emotion headers, static libraries, documentation and test programs +Group: System Environment/Libraries +Requires: %{name} = %{version} +Requires: eet-devel evas-devel edje-devel + +%description devel +Headers, static libraries, test programs and documentation for Emotion + +%prep +%setup -q + +%build +%{configure} --prefix=%{_prefix} --enable-static --enable-shared +%{__make} %{?_smp_mflags} %{?mflags} + +%install +%{__make} %{?mflags_install} DESTDIR=$RPM_BUILD_ROOT install +test -x `which doxygen` && sh gendoc || : + +# Remove useless static modules +%{__rm} -rf $RPM_BUILD_ROOT%{_libdir}/%{name}/*a + +%post +/sbin/ldconfig || : + +%postun +/sbin/ldconfig || : + +%clean +test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-, root, root) +%doc AUTHORS COPYING* README +%dir %{_libdir}/%{name} +%{_bindir}/%{name}_* +%{_libdir}/libemotion.so.* +%{_libdir}/%{name}/*.so +#%{_libdir}/xine/plugins/*/xineplug_vo_out_emotion.so +%{_datadir}/%{name} + +%files devel +%defattr(-, root, root) +%doc doc/html +%{_includedir}/emotion-1/*.h +%{_libdir}/libemotion.a +%{_libdir}/libemotion.la +%{_libdir}/libemotion.so +%{_libdir}/edje/modules/emotion/*/module.la +%{_libdir}/edje/modules/emotion/*/module.so +#%{_libdir}/xine/plugins/*/xineplug_vo_out_emotion.a +#%{_libdir}/xine/plugins/*/xineplug_vo_out_emotion.la +%{_libdir}/pkgconfig/%{name}.pc + +%changelog diff --git a/m4/ac_attribute.m4 b/m4/ac_attribute.m4 new file mode 100644 index 0000000..3926d23 --- /dev/null +++ b/m4/ac_attribute.m4 @@ -0,0 +1,46 @@ +dnl Copyright (C) 2004-2008 Kim Woelders +dnl Copyright (C) 2008 Vincent Torri +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 + +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 + +]) diff --git a/m4/efl_binary.m4 b/m4/efl_binary.m4 new file mode 100644 index 0000000..b9c9fd1 --- /dev/null +++ b/m4/efl_binary.m4 @@ -0,0 +1,44 @@ +dnl Copyright (C) 2010 Vincent Torri +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[, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +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]) + +]) diff --git a/m4/efl_doxygen.m4 b/m4/efl_doxygen.m4 new file mode 100644 index 0000000..7324af3 --- /dev/null +++ b/m4/efl_doxygen.m4 @@ -0,0 +1,94 @@ +dnl Copyright (C) 2008 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if doxygen is available or not. + +dnl EFL_CHECK_DOXYGEN([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Test for the doxygen program +dnl Defines efl_doxygen +dnl Defines the automake conditionnal EFL_BUILD_DOC +dnl +AC_DEFUN([EFL_CHECK_DOXYGEN], +[ + +dnl +dnl Disable the build of the documentation +dnl +AC_ARG_ENABLE([doc], + [AC_HELP_STRING( + [--disable-doc], + [Disable documentation build @<:@default=enabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + efl_enable_doc="yes" + else + efl_enable_doc="no" + fi + ], + [efl_enable_doc="yes"]) + +AC_MSG_CHECKING([whether to build documentation]) +AC_MSG_RESULT([${efl_enable_doc}]) + +if test "x${efl_enable_doc}" = "xyes" ; then + +dnl Specify the file name, without path + + efl_doxygen="doxygen" + + AC_ARG_WITH([doxygen], + [AC_HELP_STRING( + [--with-doxygen=FILE], + [doxygen program to use @<:@default=doxygen@:>@])], + +dnl Check the given doxygen program. + + [efl_doxygen=${withval} + AC_CHECK_PROG([efl_have_doxygen], + [${efl_doxygen}], + [yes], + [no]) + if test "x${efl_have_doxygen}" = "xno" ; then + echo "WARNING:" + echo "The doxygen program you specified:" + echo "${efl_doxygen}" + echo "was not found. Please check the path and make sure " + echo "the program exists and is executable." + AC_MSG_WARN([no doxygen detected. Documentation will not be built]) + fi + ], + [AC_CHECK_PROG([efl_have_doxygen], + [${efl_doxygen}], + [yes], + [no]) + if test "x${efl_have_doxygen}" = "xno" ; then + echo "WARNING:" + echo "The doxygen program was not found in your execute path." + echo "You may have doxygen installed somewhere not covered by your path." + echo "" + echo "If this is the case make sure you have the packages installed, AND" + echo "that the doxygen program is in your execute path (see your" + echo "shell manual page on setting the \$PATH environment variable), OR" + echo "alternatively, specify the program to use with --with-doxygen." + AC_MSG_WARN([no doxygen detected. Documentation will not be built]) + fi + ]) +else + efl_have_doxygen="no" +fi + +dnl +dnl Substitution +dnl +AC_SUBST([efl_doxygen]) + +if ! test "x${efl_have_doxygen}" = "xyes" ; then + efl_enable_doc="no" +fi + +AM_CONDITIONAL(EFL_BUILD_DOC, test "x${efl_have_doxygen}" = "xyes") + +AS_IF([test "x$efl_have_doxygen" = "xyes"], [$1], [$2]) +]) + +dnl End of efl_doxygen.m4 diff --git a/m4/efl_edje_external.m4 b/m4/efl_edje_external.m4 new file mode 100644 index 0000000..703f83e --- /dev/null +++ b/m4/efl_edje_external.m4 @@ -0,0 +1,56 @@ +dnl Copyright (C) 2010-2011 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if edje external should be enabled or not + +dnl Usage: EFL_EDJE_EXTERNAL([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Call AC_SUBST(EDJE_EXTERNAL_CFLAGS) +dnl Call AC_SUBST(EDJE_EXTERNAL_LIBS) +dnl Define conditional ENABLE_EDJE_EXTERNAL + +AC_DEFUN([EFL_EDJE_EXTERNAL], +[ + +AC_ARG_ENABLE([edje-external], + [AC_HELP_STRING([--disable-edje-external], + [disable providing Edje EXTERNAL support. @<:@default=enabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_want_edje_external="yes" + else + _efl_want_edje_external="no" + fi + ], + [_efl_want_edje_external="auto"]) + +AC_MSG_CHECKING([if should provide Edje EXTERNAL support...]) +AC_MSG_RESULT([${_efl_want_edje_external}]) + +_efl_enable_edje_external="no" +if ! test "x${_efl_want_edje_external}" = "xno" ; then + PKG_CHECK_MODULES([EDJE_EXTERNAL], + [edje >= 1.0.0], + [_efl_enable_edje_external="yes"], + [_efl_enable_edje_external="no"]) +fi + +AC_SUBST(EDJE_EXTERNAL_CFLAGS) +AC_SUBST(EDJE_EXTERNAL_LIBS) + +if test "x${_efl_want_edje_external}" = "xyes" && test "x${_efl_enable_edje_external}" = "xno" ; then + AC_MSG_ERROR([Edje EXTERNAL support requested, but Edje not found by pkg-config.]) +fi + +if test "x${_efl_enable_edje_external}" = "xyes" ; then + EDJE_VERSION=`${PKG_CONFIG} edje --modversion | awk -F . '{printf("%s.0.0", $[]1);}'` + MODULE_EDJE="$host_os-$host_cpu-${EDJE_VERSION}" + AC_DEFINE_UNQUOTED(MODULE_EDJE, "$MODULE_EDJE", "Edje module architecture") +fi + +AC_SUBST(MODULE_EDJE) + +AM_CONDITIONAL([ENABLE_EDJE_EXTERNAL], [test "x${_efl_enable_edje_external}" = "xyes"]) + +AS_IF([test "x${_efl_enable_edje_external}" = "xyes"], [$1], [$2]) + +]) diff --git a/m4/efl_examples.m4 b/m4/efl_examples.m4 new file mode 100644 index 0000000..2a809ad --- /dev/null +++ b/m4/efl_examples.m4 @@ -0,0 +1,63 @@ +dnl Copyright (C) 2008 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if building examples is wanted. + +dnl Usage: EFL_CHECK_BUILD_EXAMPLES([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Defines the automake conditionnal EFL_ENABLE_BUILD_EXAMPLES + +AC_DEFUN([EFL_CHECK_BUILD_EXAMPLES], +[ + +dnl configure option + +AC_ARG_ENABLE([build-examples], + [AC_HELP_STRING([--enable-build-examples], [enable building examples @<:@default=disabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_enable_build_examples="yes" + else + _efl_enable_build_examples="no" + fi + ], + [_efl_enable_build_examples="no"]) + +AC_MSG_CHECKING([whether examples are built]) +AC_MSG_RESULT([${_efl_enable_build_examples}]) + +AM_CONDITIONAL(EFL_BUILD_EXAMPLES, test "x${_efl_enable_build_examples}" = "xyes") + +AS_IF([test "x$_efl_enable_build_examples" = "xyes"], [$1], [$2]) +]) + + +dnl Macro that check if installing examples is wanted. + +dnl Usage: EFL_CHECK_INSTALL_EXAMPLES([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Defines the automake conditionnal EFL_ENABLE_INSTALL_EXAMPLES + +AC_DEFUN([EFL_CHECK_INSTALL_EXAMPLES], +[ + +dnl configure option + +AC_ARG_ENABLE([install-examples], + [AC_HELP_STRING([--enable-install-examples], [enable installing example source files @<:@default=disabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_enable_install_examples="yes" + else + _efl_enable_install_examples="no" + fi + ], + [_efl_enable_install_examples="no"]) + +AC_MSG_CHECKING([whether examples are installed]) +AC_MSG_RESULT([${_efl_enable_install_examples}]) + +AM_CONDITIONAL(EFL_INSTALL_EXAMPLES, test "x${_efl_enable_install_examples}" = "xyes") + +AS_IF([test "x$_efl_enable_install_examples" = "xyes"], [$1], [$2]) +]) + +dnl End of efl_examples.m4 diff --git a/m4/efl_shm_open.m4 b/m4/efl_shm_open.m4 new file mode 100644 index 0000000..0bf1b0b --- /dev/null +++ b/m4/efl_shm_open.m4 @@ -0,0 +1,69 @@ +dnl Copyright (C) 2010 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if shm_open function is available or not. + +dnl Usage: EFL_CHECK_SHM_OPEN([, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Call AC_SUBST(EFL_SHM_OPEN_LIBS) +dnl Define HAVE_SHM_OPEN to 1if shm_open is available + +AC_DEFUN([EFL_CHECK_SHM_OPEN], +[ +_efl_have_shm_open="no" + +dnl Check is shm_open is in libc + +AC_MSG_CHECKING([for shm_open in libc]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include /* For mode constants */ +#include /* For O_* constants */ + ]], + [[ +int fd; + +fd = shm_open("/dev/null", O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + ]])], + [_efl_have_shm_open="yes"], + [_efl_have_shm_open="no"]) + +AC_MSG_RESULT([${_efl_have_shm_open}]) + +if test "x$_efl_have_shm_open" = "xno" ; then + AC_MSG_CHECKING([for shm_open in librt]) + + LIBS_save="${LIBS}" + LIBS="${LIBS} -lrt" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include /* For mode constants */ +#include /* For O_* constants */ + ]], + [[ +int fd; + +fd = shm_open("/dev/null", O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + ]])], + [ + EFL_SHM_OPEN_LIBS="-lrt" + _efl_have_shm_open="yes"], + [_efl_have_shm_open="no"]) + + LIBS="${LIBS_save}" + + AC_MSG_RESULT([${_efl_have_shm_open}]) +fi + +AC_SUBST([EFL_SHM_OPEN_LIBS]) + +if test "x$_efl_have_shm_open" = "xyes" ; then + AC_DEFINE([HAVE_SHM_OPEN], [1], [Define to 1 if you have the `shm_open' function.]) +fi + +AS_IF([test "x$_efl_have_shm_open" = "xyes"], [$1], [$2]) + +]) diff --git a/m4/emotion_check.m4 b/m4/emotion_check.m4 new file mode 100644 index 0000000..043ae44 --- /dev/null +++ b/m4/emotion_check.m4 @@ -0,0 +1,216 @@ + +dnl use: EMOTION_CHECK_DEP_XINE(want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EMOTION_CHECK_DEP_XINE], +[ + +requirement="" + +PKG_CHECK_MODULES([XINE], + [libxine >= 1.1.1 evas >= 1.0.0], + [ + have_dep="yes" + requirement="libxine" + ], + [have_dep="no"]) + +if test "x$1" = "xstatic" ; then + requirement_emotion="${requirement} ${requirement_emotion}" +fi + +AS_IF([test "x$have_dep" = "xyes"], [$2], [$3]) + +]) + +dnl use: EMOTION_CHECK_DEP_GSTREAMER(want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EMOTION_CHECK_DEP_GSTREAMER], +[ + +GST_REQS=0.10.2 +GSTPLUG_REQS=0.10.1 +GST_MAJORMINOR=0.10 + +requirement="" +PKG_CHECK_MODULES([GSTREAMER], + [gstreamer-$GST_MAJORMINOR >= $GST_REQS gstreamer-plugins-base-$GST_MAJORMINOR >= $GSTPLUG_REQS gstreamer-video-$GST_MAJORMINOR >= $GSTPLUG_REQS evas >= 1.0.0 eina >= 1.1.99], + [ + have_dep="yes" + requirement="gstreamer-$GST_MAJORMINOR gstreamer-plugins-base-$GST_MAJORMINOR" + ], + [have_dep="no"]) + +if test "x$1" = "xstatic" ; then + requirement_emotion="${requirement} ${requirement_emotion}" +fi + +AS_IF([test "x$have_dep" = "xyes"], [$2], [$3]) + +]) + +dnl use: EMOTION_CHECK_DEP_GENERIC_VLC(want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EMOTION_CHECK_DEP_GENERIC_VLC], +[ + +requirement="" + +PKG_CHECK_MODULES([GENERIC_VLC], + [libvlc >= 0.9 eina >= 1.1.99], + [ + have_dep="yes" + requirement="libvlc" + ], + [have_dep="no"]) + +if test "x$1" = "xstatic" ; then + requirement_emotion="${requirement} ${requirement_emotion}" +fi + +AS_IF([test "x$have_dep" = "xyes"], [$2], [$3]) + +]) + +dnl use: EMOTION_CHECK_DEP_GENERIC(want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EMOTION_CHECK_DEP_GENERIC], +[ + +requirement="" + +PKG_CHECK_MODULES([GENERIC], + [evas >= 1.0.0], + [ + have_dep="yes" + ], + [have_dep="no"]) + +if test "x$1" = "xstatic" ; then + requirement_emotion="${requirement} ${requirement_emotion}" +fi + +AS_IF([test "x$have_dep" = "xyes"], [$2], [$3]) + +]) + +dnl use: EMOTION_CHECK_MODULE(description, want_module[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +AC_DEFUN([EMOTION_CHECK_MODULE], +[ +m4_pushdef([UP], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([$1], [-A-Z], [_a-z]))dnl + +want_module="$2" + +AC_ARG_ENABLE([DOWN], + [AC_HELP_STRING([--enable-]DOWN, [enable build of $1 module @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + enable_module="yes" + else + if test "x${enableval}" = "xstatic" ; then + enable_module="static" + else + enable_module="no" + fi + fi + ], + [enable_module="yes"]) + +if test "x${enable_module}" = "xyes" || test "x${enable_module}" = "xstatic" ; then + want_module="yes" +fi + +have_module="no" +if test "x${want_module}" = "xyes" && (test "x${enable_module}" = "xyes" || test "x${enable_module}" = "xstatic") ; then + m4_default([EMOTION_CHECK_DEP_]m4_defn([UP]))(${enable_module}, [have_module="yes"], [have_module="no"]) +fi + +AC_MSG_CHECKING([whether to enable $1 module built]) +AC_MSG_RESULT([${have_module}]) + +static_module="no" +if test "x${have_module}" = "xyes" && test "x${enable_module}" = "xstatic" ; then + static_module="yes" +fi + +AM_CONDITIONAL(EMOTION_BUILD_[]UP, [test "x${have_module}" = "xyes"]) +AM_CONDITIONAL(EMOTION_STATIC_BUILD_[]UP, [test "x${static_module}" = "xyes"]) + +if test "x${static_module}" = "xyes" ; then + AC_DEFINE(EMOTION_STATIC_BUILD_[]UP, 1, [Set to 1 if $1 is statically built]) + have_static_module="yes" +fi + +enable_[]DOWN="no" +if test "x${have_module}" = "xyes" ; then + enable_[]DOWN=${enable_module} + AC_DEFINE(EMOTION_BUILD_[]UP, 1, [Set to 1 if $1 is built]) +fi + +AS_IF([test "x$have_module" = "xyes"], [$3], [$4]) + +m4_popdef([UP]) +m4_popdef([DOWN]) +]) + +dnl use: EMOTION_CHECK_GENERIC_PLAYER(description, want_module[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +AC_DEFUN([EMOTION_CHECK_GENERIC_PLAYER], +[ +m4_pushdef([UP], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([$1], [-A-Z], [_a-z]))dnl + +want_module="$2" + +AC_ARG_ENABLE(generic-[]DOWN, + [AC_HELP_STRING([--enable-generic-]DOWN, [enable build of Generic Player $1 @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + enable_module="yes" + else + enable_module="no" + fi + ], + [enable_module="auto"]) + +# shm_open +EFL_CHECK_SHM_OPEN([have_shm_open="yes"], [have_shm_open="no"]) + +if test "x${have_shm_open}" != "xyes"; then + enable_generic="no" +fi + +if test "x${enable_generic}" != "xyes" && test "x${enable_generic}" != "xstatic"; then + if test "x${enable_module}" = "xyes"; then + AC_MSG_WARN([Generic module is disabled, force disable of Generic Player $1]) + fi + enable_module="no" + want_module="no" +fi + +if test "x${enable_module}" = "xauto"; then + enable_module="${want_module}" +elif test "x${enable_module}" = "xyes"; then + want_module="yes" +fi + +have_module="no" +if test "x${want_module}" = "xyes" && test "x${enable_module}" = "xyes"; then + m4_default([EMOTION_CHECK_DEP_GENERIC_]m4_defn([UP]))(${enable_module}, [have_module="yes"], [have_module="no"]) +fi + +AC_MSG_CHECKING([Whether to enable Generic Player $1]) +AC_MSG_RESULT([${have_module}]) + +AM_CONDITIONAL(EMOTION_BUILD_GENERIC_[]UP, [test "x${have_module}" = "xyes"]) + +enable_generic_[]DOWN="no" +if test "x${have_module}" = "xyes" ; then + enable_generic_[]DOWN=${enable_module} + AC_DEFINE(EMOTION_BUILD_GENERIC_[]UP, 1, [Set to 1 if $1 is built]) +fi + +AS_IF([test "x$have_module" = "xyes"], [$3], [$4]) + +m4_popdef([UP]) +m4_popdef([DOWN]) +]) diff --git a/m4/gst-element-check.m4 b/m4/gst-element-check.m4 new file mode 100644 index 0000000..4f4b306 --- /dev/null +++ b/m4/gst-element-check.m4 @@ -0,0 +1,23 @@ +dnl Perform a check for a GStreamer element using gst-inspect +dnl Thomas Vander Stichele +dnl Last modification: 25/01/2005 + +dnl AM_GST_ELEMENT_CHECK(ELEMENT-NAME, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([AM_GST_ELEMENT_CHECK], +[ + if test "x$GST_INSPECT" = "x"; then + AC_CHECK_PROGS(GST_INSPECT, gst-inspect gst-inspect-0.10, []) + fi + + if test "x$GST_INSPECT" != "x"; then + AC_MSG_CHECKING(GStreamer element $1) + if $GST_INSPECT $1 > /dev/null 2> /dev/null ; then + AC_MSG_RESULT(found.) + $2 + else + AC_MSG_RESULT(not found.) + $3 + fi + fi +]) diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..4082c3a --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,12 @@ + +MAINTAINERCLEANFILES = Makefile.in + +SUBDIRS = lib bin modules examples + +if ENABLE_EDJE_EXTERNAL +SUBDIRS += edje_external +endif + +if EMOTION_BUILD_GENERIC +SUBDIRS += generic_players +endif diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am new file mode 100644 index 0000000..79dd4e3 --- /dev/null +++ b/src/bin/Makefile.am @@ -0,0 +1,26 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EMOTION_CFLAGS@ \ +@EMOTION_CPPFLAGS@ \ +@EMOTION_BIN_CFLAGS@ \ +@ECORE_X_CFLAGS@ \ +@ECORE_FB_CFLAGS@ + +bin_PROGRAMS = + +if BUILD_EMOTION_TEST + +bin_PROGRAMS += emotion_test + +endif + +emotion_test_SOURCES = emotion_test_main.c + +emotion_test_LDADD = @ECORE_X_CFLAGS@ @ECORE_FB_CFLAGS@ @EMOTION_BIN_LIBS@ $(top_builddir)/src/lib/libemotion.la diff --git a/src/bin/emotion_test_main.c b/src/bin/emotion_test_main.c new file mode 100644 index 0000000..13380d6 --- /dev/null +++ b/src/bin/emotion_test_main.c @@ -0,0 +1,748 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "Emotion.h" + +static const Ecore_Getopt options = { + "emotion_test", + "%prog [options] ", + "1.0.0", + "(C) 2011 Enlightenment", + "BSD\nThis is a 3 clause bsd bla bla", + "a simple test program for emotion.", + 1, + { + ECORE_GETOPT_STORE_STR('e', "engine", "ecore-evas engine to use"), + ECORE_GETOPT_CALLBACK_NOARGS('E', "list-engines", "list ecore-evas engines", + ecore_getopt_callback_ecore_evas_list_engines, NULL), + ECORE_GETOPT_CALLBACK_ARGS('g', "geometry", "geometry to use in x:y:w:h form.", "X:Y:W:H", + ecore_getopt_callback_geometry_parse, NULL), + ECORE_GETOPT_STORE_STR('b', "backend", "backend to use"), + ECORE_GETOPT_STORE_INT('v', "vis", "visualization type"), + ECORE_GETOPT_COUNT('v', "verbose", "be more verbose"), + ECORE_GETOPT_STORE_TRUE('R', "reflex", "show video reflex effect"), + ECORE_GETOPT_VERSION('V', "version"), + ECORE_GETOPT_COPYRIGHT('R', "copyright"), + ECORE_GETOPT_LICENSE('L', "license"), + ECORE_GETOPT_HELP('h', "help"), + ECORE_GETOPT_SENTINEL + } +}; + +typedef struct _Frame_Data Frame_Data; + +struct _Frame_Data +{ + unsigned char moving : 1; + unsigned char resizing : 1; + int button; + Evas_Coord x, y; +}; + +static void main_resize(Ecore_Evas *ee); +static Eina_Bool main_signal_exit(void *data, int ev_type, void *ev); +static void main_delete_request(Ecore_Evas *ee); + +static void bg_setup(void); +static void bg_resize(Evas_Coord w, Evas_Coord h); +static void bg_key_down(void *data, Evas * e, Evas_Object * obj, void *event_info); + +static Evas_Object *o_bg = NULL; + +static double start_time = 0.0; +static Ecore_Evas *ecore_evas = NULL; +static Evas *evas = NULL; +static int startw = 800; +static int starth = 600; + +static Eina_List *video_objs = NULL; +static Emotion_Vis vis = EMOTION_VIS_NONE; +static unsigned char reflex = 0; + +static void +main_resize(Ecore_Evas *ee) +{ + Evas_Coord w, h; + + evas_output_viewport_get(ecore_evas_get(ee), NULL, NULL, &w, &h); + bg_resize(w, h); +} + +static Eina_Bool +main_signal_exit(void *data __UNUSED__, int ev_type __UNUSED__, void *ev __UNUSED__) +{ + Evas_Object *o; + + ecore_main_loop_quit(); + EINA_LIST_FREE(video_objs, o) + { + emotion_object_last_position_save(o); + evas_object_del(o); + } + return EINA_TRUE; +} + +static void +main_delete_request(Ecore_Evas *ee __UNUSED__) +{ + ecore_main_loop_quit(); +} + +void +bg_setup(void) +{ + Evas_Object *o; + + o = edje_object_add(evas); + edje_object_file_set(o, PACKAGE_DATA_DIR"/data/theme.edj", "background"); + evas_object_move(o, 0, 0); + evas_object_resize(o, startw, starth); + evas_object_layer_set(o, -999); + evas_object_show(o); + evas_object_focus_set(o, 1); + evas_object_event_callback_add(o, EVAS_CALLBACK_KEY_DOWN, bg_key_down, NULL); + o_bg = o; +} + +void +bg_resize(Evas_Coord w, Evas_Coord h) +{ + evas_object_resize(o_bg, w, h); +} + +static void +broadcast_event(Emotion_Event ev) +{ + Eina_List *l; + Evas_Object *obj; + + EINA_LIST_FOREACH(video_objs, l, obj) + emotion_object_event_simple_send(obj, ev); +} + +static void +bg_key_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + Evas_Event_Key_Down *ev = event_info; + Eina_List *l; + Evas_Object *o; + + if (!strcmp(ev->keyname, "Escape")) + ecore_main_loop_quit(); + else if (!strcmp(ev->keyname, "Up")) + broadcast_event(EMOTION_EVENT_UP); + else if (!strcmp(ev->keyname, "Down")) + broadcast_event(EMOTION_EVENT_DOWN); + else if (!strcmp(ev->keyname, "Left")) + broadcast_event(EMOTION_EVENT_LEFT); + else if (!strcmp(ev->keyname, "Right")) + broadcast_event(EMOTION_EVENT_RIGHT); + else if (!strcmp(ev->keyname, "Return")) + broadcast_event(EMOTION_EVENT_SELECT); + else if (!strcmp(ev->keyname, "m")) + broadcast_event(EMOTION_EVENT_MENU1); + else if (!strcmp(ev->keyname, "Prior")) + broadcast_event(EMOTION_EVENT_PREV); + else if (!strcmp(ev->keyname, "Next")) + broadcast_event(EMOTION_EVENT_NEXT); + else if (!strcmp(ev->keyname, "0")) + broadcast_event(EMOTION_EVENT_0); + else if (!strcmp(ev->keyname, "1")) + broadcast_event(EMOTION_EVENT_1); + else if (!strcmp(ev->keyname, "2")) + broadcast_event(EMOTION_EVENT_2); + else if (!strcmp(ev->keyname, "3")) + broadcast_event(EMOTION_EVENT_3); + else if (!strcmp(ev->keyname, "4")) + broadcast_event(EMOTION_EVENT_4); + else if (!strcmp(ev->keyname, "5")) + broadcast_event(EMOTION_EVENT_5); + else if (!strcmp(ev->keyname, "6")) + broadcast_event(EMOTION_EVENT_6); + else if (!strcmp(ev->keyname, "7")) + broadcast_event(EMOTION_EVENT_7); + else if (!strcmp(ev->keyname, "8")) + broadcast_event(EMOTION_EVENT_8); + else if (!strcmp(ev->keyname, "9")) + broadcast_event(EMOTION_EVENT_9); + else if (!strcmp(ev->keyname, "-")) + broadcast_event(EMOTION_EVENT_10); + else if (!strcmp(ev->keyname, "bracketleft")) + { + EINA_LIST_FOREACH(video_objs, l, o) + emotion_object_audio_volume_set(o, emotion_object_audio_volume_get(o) - 0.1); + } + else if (!strcmp(ev->keyname, "bracketright")) + { + EINA_LIST_FOREACH(video_objs, l, o) + emotion_object_audio_volume_set(o, emotion_object_audio_volume_get(o) + 0.1); + } + else if (!strcmp(ev->keyname, "v")) + { + EINA_LIST_FOREACH(video_objs, l, o) + { + if (emotion_object_video_mute_get(o)) + emotion_object_video_mute_set(o, 0); + else + emotion_object_video_mute_set(o, 1); + } + } + else if (!strcmp(ev->keyname, "a")) + { + EINA_LIST_FOREACH(video_objs, l, o) + { + if (emotion_object_audio_mute_get(o)) + { + emotion_object_audio_mute_set(o, 0); + printf("unmute\n"); + } + else + { + emotion_object_audio_mute_set(o, 1); + printf("mute\n"); + } + } + } + else if (!strcmp(ev->keyname, "i")) + { + EINA_LIST_FOREACH(video_objs, l, o) + { + printf("audio channels: %i\n", emotion_object_audio_channel_count(o)); + printf("video channels: %i\n", emotion_object_video_channel_count(o)); + printf("spu channels: %i\n", emotion_object_spu_channel_count(o)); + printf("seekable: %i\n", emotion_object_seekable_get(o)); + } + } + else if (!strcmp(ev->keyname, "f")) + { + if (!ecore_evas_fullscreen_get(ecore_evas)) + ecore_evas_fullscreen_set(ecore_evas, 1); + else + ecore_evas_fullscreen_set(ecore_evas, 0); + } + else if (!strcmp(ev->keyname, "d")) + { + if (!ecore_evas_avoid_damage_get(ecore_evas)) + ecore_evas_avoid_damage_set(ecore_evas, 1); + else + ecore_evas_avoid_damage_set(ecore_evas, 0); + } + else if (!strcmp(ev->keyname, "s")) + { + if (!ecore_evas_shaped_get(ecore_evas)) + { + ecore_evas_shaped_set(ecore_evas, 1); + evas_object_hide(o_bg); + } + else + { + ecore_evas_shaped_set(ecore_evas, 0); + evas_object_show(o_bg); + } + } + else if (!strcmp(ev->keyname, "b")) + { + if (!ecore_evas_borderless_get(ecore_evas)) + ecore_evas_borderless_set(ecore_evas, 1); + else + ecore_evas_borderless_set(ecore_evas, 0); + } + else if (!strcmp(ev->keyname, "q")) + { + ecore_main_loop_quit(); + while (video_objs) + { + printf("del obj!\n"); + evas_object_del(video_objs->data); + video_objs = eina_list_remove_list(video_objs, video_objs); + printf("done\n"); + } + } + else if (!strcmp(ev->keyname, "z")) + { + vis = (vis + 1) % EMOTION_VIS_LAST; + printf("new visualization: %d\n", vis); + + EINA_LIST_FOREACH(video_objs, l, o) + { + Eina_Bool supported; + + supported = emotion_object_vis_supported(o, vis); + if (supported) + emotion_object_vis_set(o, vis); + else + { + const char *file; + + file = emotion_object_file_get(o); + printf("object %p (%s) does not support visualization %d\n", + o, file, vis); + } + } + } + else + { + printf("UNHANDLED: %s\n", ev->keyname); + } +} + +static void +video_obj_time_changed(Evas_Object *obj, Evas_Object *edje) +{ + double pos, len, scale; + char buf[256]; + int ph, pm, ps, pf, lh, lm, ls; + + pos = emotion_object_position_get(obj); + len = emotion_object_play_length_get(obj); + scale = (len > 0.0) ? pos / len : 0.0; + edje_object_part_drag_value_set(edje, "video_progress", scale, 0.0); + lh = len / 3600; + lm = len / 60 - (lh * 60); + ls = len - (lm * 60); + ph = pos / 3600; + pm = pos / 60 - (ph * 60); + ps = pos - (pm * 60); + pf = pos * 100 - (ps * 100) - (pm * 60 * 100) - (ph * 60 * 60 * 100); + snprintf(buf, sizeof(buf), "%i:%02i:%02i.%02i / %i:%02i:%02i", + ph, pm, ps, pf, lh, lm, ls); + edje_object_part_text_set(edje, "video_progress_txt", buf); +} + +static void +video_obj_frame_decode_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) +{ + video_obj_time_changed(obj, data); + + if (0) + { + double t; + static double pt = 0.0; + t = ecore_time_get(); + printf("FPS: %3.3f\n", 1.0 / (t - pt)); + pt = t; + } +} + +static void +video_obj_frame_resize_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) +{ + Evas_Object *oe; + int iw, ih; + Evas_Coord w, h; + double ratio; + + oe = data; + emotion_object_size_get(obj, &iw, &ih); + ratio = emotion_object_ratio_get(obj); + printf("HANDLE %ix%i @ %3.3f\n", iw, ih, ratio); + if (ratio > 0.0) iw = (ih * ratio) + 0.5; + edje_extern_object_min_size_set(obj, iw, ih); + edje_object_part_swallow(oe, "video_swallow", obj); + edje_object_size_min_calc(oe, &w, &h); + evas_object_resize(oe, w, h); + edje_extern_object_min_size_set(obj, 0, 0); + edje_object_part_swallow(oe, "video_swallow", obj); +} + +static void +video_obj_length_change_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) +{ + video_obj_time_changed(obj, data); +} + +static void +video_obj_position_update_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) +{ + video_obj_time_changed(obj, data); +} + +static void +video_obj_stopped_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + printf("video stopped!\n"); + emotion_object_position_set(obj, 0.0); + emotion_object_play_set(obj, 1); +} + +static void +video_obj_channels_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + printf("channels changed: [AUD %i][VID %i][SPU %i]\n", + emotion_object_audio_channel_count(obj), + emotion_object_video_channel_count(obj), + emotion_object_spu_channel_count(obj)); +} + +static void +video_obj_title_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + printf("video title to: \"%s\"\n", emotion_object_title_get(obj)); +} + +static void +video_obj_progress_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + printf("progress: \"%s\" %3.3f\n", + emotion_object_progress_info_get(obj), + emotion_object_progress_status_get(obj)); +} + +static void +video_obj_ref_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + printf("video ref to: \"%s\" %i\n", + emotion_object_ref_file_get(obj), + emotion_object_ref_num_get(obj)); +} + +static void +video_obj_button_num_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + printf("video spu buttons to: %i\n", + emotion_object_spu_button_count_get(obj)); +} + +static void +video_obj_button_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + printf("video selected spu button: %i\n", + emotion_object_spu_button_get(obj)); +} + + + +static void +video_obj_signal_play_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Evas_Object *ov = data; + emotion_object_play_set(ov, 1); + edje_object_signal_emit(o, "video_state", "play"); +} + +static void +video_obj_signal_pause_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Evas_Object *ov = data; + emotion_object_play_set(ov, 0); + edje_object_signal_emit(o, "video_state", "pause"); +} + +static void +video_obj_signal_stop_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Evas_Object *ov = data; + emotion_object_play_set(ov, 0); + emotion_object_position_set(ov, 0); + edje_object_signal_emit(o, "video_state", "stop"); +} + +static void +video_obj_signal_jump_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Evas_Object *ov = data; + double len; + double x, y; + + edje_object_part_drag_value_get(o, source, &x, &y); + len = emotion_object_play_length_get(ov); + emotion_object_position_set(ov, x * len); +} + +static void +video_obj_signal_speed_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Evas_Object *ov = data; + double spd; + double x, y; + char buf[256]; + + edje_object_part_drag_value_get(o, source, &x, &y); + spd = 255 * y; + evas_object_color_set(ov, spd, spd, spd, spd); + snprintf(buf, sizeof(buf), "%.0f", spd); + edje_object_part_text_set(o, "video_speed_txt", buf); +} + +static void +video_obj_signal_frame_move_start_cb(void *data __UNUSED__, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Frame_Data *fd; + Evas_Coord x, y; + + fd = evas_object_data_get(o, "frame_data"); + fd->moving = 1; + evas_pointer_canvas_xy_get(evas_object_evas_get(o), &x, &y); + fd->x = x; + fd->y = y; + evas_object_raise(o); +} + +static void +video_obj_signal_frame_move_stop_cb(void *data __UNUSED__, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Frame_Data *fd; + + fd = evas_object_data_get(o, "frame_data"); + fd->moving = 0; +} + +static void +video_obj_signal_frame_resize_start_cb(void *data __UNUSED__, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Frame_Data *fd; + Evas_Coord x, y; + + fd = evas_object_data_get(o, "frame_data"); + fd->resizing = 1; + evas_pointer_canvas_xy_get(evas_object_evas_get(o), &x, &y); + fd->x = x; + fd->y = y; + evas_object_raise(o); +} + +static void +video_obj_signal_frame_resize_stop_cb(void *data __UNUSED__, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Frame_Data *fd; + + fd = evas_object_data_get(o, "frame_data"); + fd->resizing = 0; +} + +static void +video_obj_signal_frame_move_cb(void *data __UNUSED__, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Frame_Data *fd; + + fd = evas_object_data_get(o, "frame_data"); + if (fd->moving) + { + Evas_Coord x, y, ox, oy; + + evas_pointer_canvas_xy_get(evas_object_evas_get(o), &x, &y); + evas_object_geometry_get(o, &ox, &oy, NULL, NULL); + evas_object_move(o, ox + (x - fd->x), oy + (y - fd->y)); + fd->x = x; + fd->y = y; + } + else if (fd->resizing) + { + Evas_Coord x, y, ow, oh; + + evas_pointer_canvas_xy_get(evas_object_evas_get(o), &x, &y); + evas_object_geometry_get(o, NULL, NULL, &ow, &oh); + evas_object_resize(o, ow + (x - fd->x), oh + (y - fd->y)); + fd->x = x; + fd->y = y; + } +} + + +static void +init_video_object(const char *module_filename, const char *filename) +{ + Evas_Object *o, *oe; + int iw, ih; + Evas_Coord w, h; + Frame_Data *fd; + + +/* basic video object setup */ + o = emotion_object_add(evas); + if (!emotion_object_init(o, module_filename)) + return; + emotion_object_vis_set(o, vis); + if (!emotion_object_file_set(o, filename)) + { + return; + } + emotion_object_last_position_load(o); + emotion_object_play_set(o, 1); + evas_object_move(o, 0, 0); + evas_object_resize(o, 320, 240); + emotion_object_smooth_scale_set(o, 1); + evas_object_show(o); +/* end basic video setup. all the rest here is just to be fancy */ + + + video_objs = eina_list_append(video_objs, o); + + emotion_object_size_get(o, &iw, &ih); + w = iw; h = ih; + + fd = calloc(1, sizeof(Frame_Data)); + + oe = edje_object_add(evas); + evas_object_data_set(oe, "frame_data", fd); + if (reflex) + edje_object_file_set(oe, PACKAGE_DATA_DIR"/data/theme.edj", "video_controller/reflex"); + else + edje_object_file_set(oe, PACKAGE_DATA_DIR"/data/theme.edj", "video_controller"); + edje_extern_object_min_size_set(o, w, h); + edje_object_part_swallow(oe, "video_swallow", o); + edje_object_size_min_calc(oe, &w, &h); +// evas_object_move(oe, rand() % (int)(startw - w), rand() % (int)(starth - h)); + evas_object_move(oe, 0, 0); + evas_object_resize(oe, w, h); + edje_extern_object_min_size_set(o, 0, 0); + edje_object_part_swallow(oe, "video_swallow", o); + + evas_object_smart_callback_add(o, "frame_decode", video_obj_frame_decode_cb, oe); + evas_object_smart_callback_add(o, "frame_resize", video_obj_frame_resize_cb, oe); + evas_object_smart_callback_add(o, "length_change", video_obj_length_change_cb, oe); + evas_object_smart_callback_add(o, "position_update", video_obj_position_update_cb, oe); + + evas_object_smart_callback_add(o, "decode_stop", video_obj_stopped_cb, oe); + evas_object_smart_callback_add(o, "channels_change", video_obj_channels_cb, oe); + evas_object_smart_callback_add(o, "title_change", video_obj_title_cb, oe); + evas_object_smart_callback_add(o, "progress_change", video_obj_progress_cb, oe); + evas_object_smart_callback_add(o, "ref_change", video_obj_ref_cb, oe); + evas_object_smart_callback_add(o, "button_num_change", video_obj_button_num_cb, oe); + evas_object_smart_callback_add(o, "button_change", video_obj_button_cb, oe); + + edje_object_signal_callback_add(oe, "video_control", "play", video_obj_signal_play_cb, o); + edje_object_signal_callback_add(oe, "video_control", "pause", video_obj_signal_pause_cb, o); + edje_object_signal_callback_add(oe, "video_control", "stop", video_obj_signal_stop_cb, o); + edje_object_signal_callback_add(oe, "drag", "video_progress", video_obj_signal_jump_cb, o); + edje_object_signal_callback_add(oe, "drag", "video_speed", video_obj_signal_speed_cb, o); + + edje_object_signal_callback_add(oe, "frame_move", "start", video_obj_signal_frame_move_start_cb, oe); + edje_object_signal_callback_add(oe, "frame_move", "stop", video_obj_signal_frame_move_stop_cb, oe); + edje_object_signal_callback_add(oe, "frame_resize", "start", video_obj_signal_frame_resize_start_cb, oe); + edje_object_signal_callback_add(oe, "frame_resize", "stop", video_obj_signal_frame_resize_stop_cb, oe); + edje_object_signal_callback_add(oe, "mouse,move", "*", video_obj_signal_frame_move_cb, oe); + + edje_object_part_drag_value_set(oe, "video_speed", 0.0, 1.0); + edje_object_part_text_set(oe, "video_speed_txt", "1.0"); + + edje_object_signal_emit(o, "video_state", "play"); + + evas_object_show(oe); +} + +static Eina_Bool +check_positions(void *data __UNUSED__) +{ + const Eina_List *lst; + Evas_Object *o; + + EINA_LIST_FOREACH(video_objs, lst, o) + video_obj_time_changed(o, evas_object_smart_parent_get(o)); + + return !!video_objs; +} + +int +main(int argc, char **argv) +{ + int args; + Eina_Rectangle geometry = {0, 0, startw, starth}; + char *engine = NULL; + char *backend = NULL; + int verbose = 0; + int visual = EMOTION_VIS_NONE; + unsigned char help = 0; + unsigned char engines_listed = 0; + Ecore_Getopt_Value values[] = { + ECORE_GETOPT_VALUE_STR(engine), + ECORE_GETOPT_VALUE_BOOL(engines_listed), + ECORE_GETOPT_VALUE_PTR_CAST(geometry), + ECORE_GETOPT_VALUE_STR(backend), + ECORE_GETOPT_VALUE_INT(visual), + ECORE_GETOPT_VALUE_INT(verbose), + ECORE_GETOPT_VALUE_BOOL(reflex), + ECORE_GETOPT_VALUE_NONE, + ECORE_GETOPT_VALUE_NONE, + ECORE_GETOPT_VALUE_NONE, + ECORE_GETOPT_VALUE_BOOL(help), + ECORE_GETOPT_VALUE_NONE + }; + + + if (!ecore_evas_init()) + return -1; + if (!edje_init()) + goto shutdown_ecore_evas; + + start_time = ecore_time_get(); + ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, NULL); + edje_frametime_set(1.0 / 30.0); + + ecore_app_args_set(argc, (const char **)argv); + args = ecore_getopt_parse(&options, values, argc, argv); + if (args < 0) goto shutdown_edje; + else if (help) goto shutdown_edje; + else if (engines_listed) goto shutdown_edje; + else if (args == argc) + { + printf("must provide at least one file to play!\n"); + goto shutdown_edje; + } + + if ((geometry.w == 0) || (geometry.h == 0)) + { + if (geometry.w == 0) geometry.w = 320; + if (geometry.h == 0) geometry.h = 240; + } + + printf("evas engine: %s\n", engine ? engine : ""); + printf("emotion backend: %s\n", backend ? backend : ""); + printf("vis: %d\n", vis); + printf("geometry: %d %d %dx%d\n", geometry.x, geometry.y, geometry.w, geometry.h); + + ecore_evas = ecore_evas_new + (engine, geometry.x, geometry.y, geometry.w, geometry.h, NULL); + if (!ecore_evas) + goto shutdown_edje; + +// ecore_evas_alpha_set(ecore_evas, EINA_TRUE); + + ecore_evas_callback_delete_request_set(ecore_evas, main_delete_request); + ecore_evas_callback_resize_set(ecore_evas, main_resize); + ecore_evas_title_set(ecore_evas, "Evas Media Test Program"); + ecore_evas_name_class_set(ecore_evas, "evas_media_test", "main"); + ecore_evas_show(ecore_evas); + evas = ecore_evas_get(ecore_evas); + evas_image_cache_set(evas, 8 * 1024 * 1024); + evas_font_cache_set(evas, 1 * 1024 * 1024); + evas_font_path_append(evas, PACKAGE_DATA_DIR"/data/fonts"); + + emotion_init(); + + bg_setup(); + + for (; args < argc; args++) + init_video_object(backend, argv[args]); + + ecore_animator_add(check_positions, NULL); + + ecore_main_loop_begin(); + + main_signal_exit(NULL, 0, NULL); + + emotion_shutdown(); + ecore_evas_free(ecore_evas); + ecore_evas_shutdown(); + edje_shutdown(); + + return 0; + + shutdown_edje: + edje_shutdown(); + shutdown_ecore_evas: + ecore_evas_shutdown(); + + return -1; +} diff --git a/src/edje_external/Makefile.am b/src/edje_external/Makefile.am new file mode 100644 index 0000000..9b36faf --- /dev/null +++ b/src/edje_external/Makefile.am @@ -0,0 +1,18 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EMOTION_CPPFLAGS@ \ +@EMOTION_CFLAGS@ \ +@EDJE_EXTERNAL_CFLAGS@ \ +@EFL_EMOTION_BUILD@ + +pkgdir = $(libdir)/edje/modules/emotion/$(MODULE_EDJE) +pkg_LTLIBRARIES = module.la + +module_la_SOURCES = emotion.c +module_la_LIBADD = @EMOTION_LIBS@ $(top_builddir)/src/lib/libemotion.la @EDJE_EXTERNAL_LIBS@ +module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +module_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/src/edje_external/emotion.c b/src/edje_external/emotion.c new file mode 100644 index 0000000..d7fc012 --- /dev/null +++ b/src/edje_external/emotion.c @@ -0,0 +1,516 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "Emotion.h" + +typedef struct _External_Emotion_Params External_Emotion_Params; +typedef struct _External_Emotion_Signals_Proxy_Context External_Emotion_Signals_Proxy_Context; + +struct _External_Emotion_Params +{ +#define _STR(M) const char *M +#define _BOOL(M) Eina_Bool M:1; Eina_Bool M##_exists:1 +#define _INT(M) int M; Eina_Bool M##_exists:1 +#define _DOUBLE(M) double M; Eina_Bool M##_exists:1 + _STR(file); + _BOOL(play); + _DOUBLE(position); + _BOOL(smooth_scale); + _DOUBLE(audio_volume); + _BOOL(audio_mute); + _INT(audio_channel); + _BOOL(video_mute); + _INT(video_channel); + _BOOL(spu_mute); + _INT(spu_channel); + _INT(chapter); + _DOUBLE(play_speed); + _DOUBLE(play_length); + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE +}; + +struct _External_Emotion_Signals_Proxy_Context +{ + const char *emission; + const char *source; + Evas_Object *edje; +}; + +static int _log_dom = -1; +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) +#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__) + +static const char *_external_emotion_engines[] = { +#ifdef EMOTION_BUILD_XINE + "xine", +#endif +#ifdef EMOTION_BUILD_GSTREAMER + "gstreamer", +#endif +#ifdef EMOTION_BUILD_GENERIC + "generic", +#endif + NULL, +}; + +static const char _external_emotion_engine_def[] = +#if defined(EMOTION_BUILD_XINE) + "xine"; +#elif defined(EMOTION_BUILD_GSTREAMER) + "gstreamer"; +#elif defined(EMOTION_BUILD_GENERIC) + "generic"; +#else + "impossible"; +#endif + +static void +_external_emotion_signal_proxy_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + External_Emotion_Signals_Proxy_Context *ctxt = data; + free(ctxt); +} + +static void +_external_emotion_signal_proxy_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + External_Emotion_Signals_Proxy_Context *ctxt = data; + // TODO: Is it worth to check Evas_Smart_Cb_Description and do something + // TODO: with event_info given its description? + edje_object_signal_emit(ctxt->edje, ctxt->emission, ctxt->source); +} + +static Evas_Object * +_external_emotion_add(void *data __UNUSED__, Evas *evas, Evas_Object *edje __UNUSED__, const Eina_List *params, const char *part_name) +{ + const Evas_Smart_Cb_Description **cls_descs, **inst_descs; + unsigned int cls_count, inst_count, total; + External_Emotion_Signals_Proxy_Context *ctxt; + Evas_Object *obj; + const char *engine; + + if (!edje_external_param_choice_get(params, "engine", &engine)) + engine = NULL; + if (!engine) engine = _external_emotion_engine_def; + + obj = emotion_object_add(evas); + if (!emotion_object_init(obj, engine)) + { + ERR("failed to initialize emotion with engine '%s'.", engine); + return NULL; + } + + evas_object_smart_callbacks_descriptions_get + (obj, &cls_descs, &cls_count, &inst_descs, &inst_count); + + total = cls_count + inst_count; + if (!total) goto end; + ctxt = malloc(sizeof(External_Emotion_Signals_Proxy_Context) * total); + if (!ctxt) goto end; + evas_object_event_callback_add + (obj, EVAS_CALLBACK_DEL, _external_emotion_signal_proxy_free_cb, ctxt); + + for (; cls_count > 0; cls_count--, cls_descs++, ctxt++) + { + const Evas_Smart_Cb_Description *d = *cls_descs; + ctxt->emission = d->name; + ctxt->source = part_name; + ctxt->edje = edje; + evas_object_smart_callback_add + (obj, d->name, _external_emotion_signal_proxy_cb, ctxt); + } + + for (; inst_count > 0; inst_count--, inst_descs++, ctxt++) + { + const Evas_Smart_Cb_Description *d = *inst_descs; + ctxt->emission = d->name; + ctxt->source = part_name; + ctxt->edje = edje; + evas_object_smart_callback_add + (obj, d->name, _external_emotion_signal_proxy_cb, ctxt); + } + + end: + return obj; +} + +static void +_external_emotion_signal(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *signal, const char *source) +{ + DBG("External Signal received: '%s' '%s'", signal, source); +} + +static void +_external_emotion_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__) +{ + const External_Emotion_Params *p; + + if (to_params) p = to_params; + else if (from_params) p = from_params; + else return; + +#define _STR(M) if (p->M) emotion_object_##M##_set(obj, p->M) +#define _BOOL(M) if (p->M##_exists) emotion_object_##M##_set(obj, p->M) +#define _INT(M) if (p->M##_exists) emotion_object_##M##_set(obj, p->M) +#define _DOUBLE(M) if (p->M##_exists) emotion_object_##M##_set(obj, p->M) + _STR(file); + _BOOL(play); + //_DOUBLE(position); + if (p->position_exists) + WRN("position should not be set from state description! Ignored."); + _BOOL(smooth_scale); + _DOUBLE(audio_volume); + _BOOL(audio_mute); + _INT(audio_channel); + _BOOL(video_mute); + _INT(video_channel); + _BOOL(spu_mute); + _INT(spu_channel); + _INT(chapter); + _DOUBLE(play_speed); + if (p->play_length_exists) ERR("play_length is read-only"); + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE +} + +static Eina_Bool +_external_emotion_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param) +{ + if (!strcmp(param->name, "engine")) + { + // TODO + WRN("engine is a property that can be set only at object creation!"); + return EINA_FALSE; + } + +#define _STR(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING) \ + { \ + emotion_object_##M##_set(obj, param->s); \ + return EINA_TRUE; \ + } \ + } +#define _BOOL(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL) \ + { \ + emotion_object_##M##_set(obj, param->i); \ + return EINA_TRUE; \ + } \ + } +#define _INT(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT) \ + { \ + emotion_object_##M##_set(obj, param->i); \ + return EINA_TRUE; \ + } \ + } +#define _DOUBLE(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE) \ + { \ + emotion_object_##M##_set(obj, param->d); \ + return EINA_TRUE; \ + } \ + } + + if (0) {} // so else if works... + _STR(file) + _BOOL(play) + _DOUBLE(position) + _BOOL(smooth_scale) + _DOUBLE(audio_volume) + _BOOL(audio_mute) + _INT(audio_channel) + _BOOL(video_mute) + _INT(video_channel) + _BOOL(spu_mute) + _INT(spu_channel) + _INT(chapter) + _DOUBLE(play_speed) + else if (!strcmp(param->name, "play_length")) + { + ERR("play_length is read-only"); + return EINA_FALSE; + } + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE + + ERR("unknown parameter '%s' of type '%s'", + param->name, edje_external_param_type_str(param->type)); + + return EINA_FALSE; +} + +static Eina_Bool +_external_emotion_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param) +{ +#define _STR(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING) \ + { \ + param->s = emotion_object_##M##_get(obj); \ + return EINA_TRUE; \ + } \ + } +#define _BOOL(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL) \ + { \ + param->i = emotion_object_##M##_get(obj); \ + return EINA_TRUE; \ + } \ + } +#define _INT(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT) \ + { \ + param->i = emotion_object_##M##_get(obj); \ + return EINA_TRUE; \ + } \ + } +#define _DOUBLE(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE) \ + { \ + param->d = emotion_object_##M##_get(obj); \ + return EINA_TRUE; \ + } \ + } + + if (0) {} // so else if works... + _STR(file) + _BOOL(play) + _DOUBLE(position) + _BOOL(smooth_scale) + _DOUBLE(audio_volume) + _BOOL(audio_mute) + _INT(audio_channel) + _BOOL(video_mute) + _INT(video_channel) + _BOOL(spu_mute) + _INT(spu_channel) + _INT(chapter) + _DOUBLE(play_speed) + _DOUBLE(play_length) + //_INT(vis) +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE + + ERR("unknown parameter '%s' of type '%s'", + param->name, edje_external_param_type_str(param->type)); + + return EINA_FALSE; +} + +static void * +_external_emotion_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params) +{ + const Edje_External_Param *param; + const Eina_List *l; + External_Emotion_Params *p = calloc(1, sizeof(External_Emotion_Params)); + if (!p) return NULL; + + EINA_LIST_FOREACH(params, l, param) + { +#define _STR(M) \ + if (!strcmp(param->name, #M)) p->M = eina_stringshare_add(param->s) +#define _BOOL(M) \ + if (!strcmp(param->name, #M)) \ + { \ + p->M = param->i; \ + p->M##_exists = EINA_TRUE; \ + } +#define _INT(M) \ + if (!strcmp(param->name, #M)) \ + { \ + p->M = param->i; \ + p->M##_exists = EINA_TRUE; \ + } +#define _DOUBLE(M) \ + if (!strcmp(param->name, #M)) \ + { \ + p->M = param->d; \ + p->M##_exists = EINA_TRUE; \ + } + + _STR(file); + _BOOL(play); + _DOUBLE(position); + _BOOL(smooth_scale); + _DOUBLE(audio_volume); + _BOOL(audio_mute); + _INT(audio_channel); + _BOOL(video_mute); + _INT(video_channel); + _BOOL(spu_mute); + _INT(spu_channel); + _INT(chapter); + _DOUBLE(play_speed); + _DOUBLE(play_length); + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE + } + + return p; +} + +static void +_external_emotion_params_free(void *params) +{ + External_Emotion_Params *p = params; + +#define _STR(M) eina_stringshare_del(p->M) +#define _BOOL(M) do {} while (0) +#define _INT(M) do {} while (0) +#define _DOUBLE(M) do {} while (0) + _STR(file); + _BOOL(play); + _DOUBLE(position); + _BOOL(smooth_scale); + _DOUBLE(audio_volume); + _BOOL(audio_mute); + _INT(audio_channel); + _BOOL(video_mute); + _INT(video_channel); + _BOOL(spu_mute); + _INT(spu_channel); + _INT(chapter); + _DOUBLE(play_speed); + _DOUBLE(play_length); + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE + free(p); +} + +static const char * +_external_emotion_label_get(void *data __UNUSED__) +{ + return "Emotion"; +} + +static Evas_Object * +_external_emotion_icon_add(void *data __UNUSED__, Evas *e) +{ + Evas_Object *ic; + int w = 0, h = 0; + + ic = edje_object_add(e); + edje_object_file_set(ic, PACKAGE_DATA_DIR"/data/icon.edj", "icon"); + edje_object_size_min_get(ic, &w, &h); + if (w < 1) w = 20; + if (h < 1) h = 10; + evas_object_size_hint_min_set(ic, w, h); + evas_object_size_hint_max_set(ic, w, h); + + return ic; +} + +static const char * +_external_emotion_translate(void *data __UNUSED__, const char *orig) +{ + // in future, mark all params as translatable and use dgettext() + // with "emotion" text domain here. + return orig; +} + +static Edje_External_Param_Info _external_emotion_params[] = { + EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL + ("engine", _external_emotion_engine_def, _external_emotion_engines), + EDJE_EXTERNAL_PARAM_INFO_STRING("file"), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("play", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_DOUBLE("position"), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("smooth_scale", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_DOUBLE_DEFAULT("audio_volume", 0.9), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("audio_mute", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_INT_DEFAULT("audio_channel", 0), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("video_mute", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_INT_DEFAULT("video_channel", 0), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("spu_mute", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_INT_DEFAULT("spu_channel", 0), + EDJE_EXTERNAL_PARAM_INFO_INT("chapter"), + EDJE_EXTERNAL_PARAM_INFO_DOUBLE_DEFAULT("play_speed", 1.0), + EDJE_EXTERNAL_PARAM_INFO_DOUBLE("play_length"), + //EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("vis", ...), + EDJE_EXTERNAL_PARAM_INFO_SENTINEL +}; + +static const Edje_External_Type _external_emotion_type = { + .abi_version = EDJE_EXTERNAL_TYPE_ABI_VERSION, + .module = "emotion", + .module_name = "Emotion", + .add = _external_emotion_add, + .state_set = _external_emotion_state_set, + .signal_emit = _external_emotion_signal, + .param_set = _external_emotion_param_set, + .param_get = _external_emotion_param_get, + .params_parse = _external_emotion_params_parse, + .params_free = _external_emotion_params_free, + .label_get = _external_emotion_label_get, + .description_get = NULL, + .icon_add = _external_emotion_icon_add, + .preview_add = NULL, + .translate = _external_emotion_translate, + .parameters_info = _external_emotion_params, + .data = NULL +}; + +static Edje_External_Type_Info _external_emotion_types[] = +{ + {"emotion", &_external_emotion_type}, + {NULL, NULL} +}; + +static Eina_Bool +external_emotion_mod_init(void) +{ + _log_dom = eina_log_domain_register + ("emotion-externals", EINA_COLOR_LIGHTBLUE); + edje_external_type_array_register(_external_emotion_types); + return EINA_TRUE; +} + +static void +external_emotion_mod_shutdown(void) +{ + edje_external_type_array_unregister(_external_emotion_types); + eina_log_domain_unregister(_log_dom); + _log_dom = -1; +} + +EINA_MODULE_INIT(external_emotion_mod_init); +EINA_MODULE_SHUTDOWN(external_emotion_mod_shutdown); diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am new file mode 100644 index 0000000..7476f08 --- /dev/null +++ b/src/examples/Makefile.am @@ -0,0 +1,39 @@ +MAINTAINERCLEANFILES = Makefile.in + +examplesdir = $(datadir)/$(PACKAGE)/examples + +AM_CPPFLAGS = \ +-I. \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +@EMOTION_CFLAGS@ \ +@EMOTION_CPPFLAGS@ \ +@EMOTION_BIN_CFLAGS@ + +LDADD = \ + $(top_builddir)/src/lib/libemotion.la \ + @EMOTION_BIN_LIBS@ + +SRCS = \ + emotion_basic_example.c \ + emotion_generic_example.c \ + emotion_border_example.c \ + emotion_signals_example.c + +EXTRA_DIST = $(SRCS) + +examples_PROGRAMS = + +if EFL_INSTALL_EXAMPLES +filesdir = $(datadir)/$(PACKAGE)/examples +files_DATA = $(SRCS) +endif + +if EFL_BUILD_EXAMPLES +examples_PROGRAMS += \ + emotion_basic_example \ + emotion_generic_example \ + emotion_border_example \ + emotion_signals_example +endif + diff --git a/src/examples/emotion_basic_example.c b/src/examples/emotion_basic_example.c new file mode 100644 index 0000000..7e3e4c2 --- /dev/null +++ b/src/examples/emotion_basic_example.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +#define WIDTH (320) +#define HEIGHT (240) + +static void +_playback_started_cb(void *data, Evas_Object *o, void *event_info) +{ + printf("Emotion object started playback.\n"); +} + +int +main(int argc, const char *argv[]) +{ + Ecore_Evas *ee; + Evas *e; + Evas_Object *bg, *em; + const char *filename = NULL; + + if (argc < 2) + { + printf("One argument is necessary. Usage:\n"); + printf("\t%s \n", argv[0]); + } + + filename = argv[1]; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL); + if (!ee) + goto error; + + ecore_evas_show(ee); + + /* the canvas pointer, de facto */ + e = ecore_evas_get(ee); + + /* adding a background to this example */ + bg = evas_object_rectangle_add(e); + evas_object_name_set(bg, "our dear rectangle"); + evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */ + evas_object_move(bg, 0, 0); /* at canvas' origin */ + evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */ + evas_object_show(bg); + + /* Creating the emotion object */ + em = emotion_object_add(e); + emotion_object_init(em, NULL); + + evas_object_smart_callback_add( + em, "playback_started", _playback_started_cb, NULL); + + emotion_object_file_set(em, filename); + + evas_object_move(em, 0, 0); + evas_object_resize(em, WIDTH, HEIGHT); + evas_object_show(em); + + emotion_object_play_set(em, EINA_TRUE); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + return 0; + +error: + fprintf(stderr, "you got to have at least one evas engine built and linked" + " up to ecore-evas for this example to run properly.\n"); + + ecore_evas_shutdown(); + return -1; +} diff --git a/src/examples/emotion_border_example.c b/src/examples/emotion_border_example.c new file mode 100644 index 0000000..9df53f4 --- /dev/null +++ b/src/examples/emotion_border_example.c @@ -0,0 +1,238 @@ +#include +#include +#include +#include +#include +#include + +#define WIDTH (320) +#define HEIGHT (240) + +static Eina_List *filenames = NULL; +static Eina_List *curfile = NULL; + +static void +_playback_started_cb(void *data, Evas_Object *o, void *event_info) +{ + printf("Emotion object started playback.\n"); +} + +static Evas_Object * +_create_emotion_object(Evas *e) +{ + Evas_Object *em = emotion_object_add(e); + + emotion_object_init(em, "gstreamer"); + + evas_object_smart_callback_add( + em, "playback_started", _playback_started_cb, NULL); + + return em; +} + +static void +_on_key_down(void *data, Evas *e, Evas_Object *o, void *event_info) +{ + Evas_Event_Key_Down *ev = event_info; + Evas_Object *em = data; + + if (!strcmp(ev->keyname, "Return")) + { + emotion_object_play_set(em, EINA_TRUE); + } + else if (!strcmp(ev->keyname, "space")) + { + emotion_object_play_set(em, EINA_FALSE); + } + else if (!strcmp(ev->keyname, "Escape")) + { + ecore_main_loop_quit(); + } + else if (!strcmp(ev->keyname, "n")) + { + const char *file; + if (!curfile) + curfile = filenames; + else + curfile = eina_list_next(curfile); + file = eina_list_data_get(curfile); + fprintf(stderr, "playing next file: %s\n", file); + emotion_object_file_set(em, file); + } + else if (!strcmp(ev->keyname, "p")) + { + const char *file; + if (!curfile) + curfile = eina_list_last(filenames); + else + curfile = eina_list_prev(curfile); + file = eina_list_data_get(curfile); + fprintf(stderr, "playing next file: %s\n", file); + emotion_object_file_set(em, file); + } + else if (!strcmp(ev->keyname, "b")) + { + emotion_object_border_set(em, 0, 0, 50, 50); + } + else if (!strcmp(ev->keyname, "0")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_NONE); + } + else if (!strcmp(ev->keyname, "w")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_WIDTH); + } + else if (!strcmp(ev->keyname, "h")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_HEIGHT); + } + else if (!strcmp(ev->keyname, "2")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_BOTH); + } + else if (!strcmp(ev->keyname, "c")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_CROP); + } + else + { + fprintf(stderr, "unhandled key: %s\n", ev->keyname); + } +} + +static void +_frame_decode_cb(void *data, Evas_Object *o, void *event_info) +{ + // fprintf(stderr, "smartcb: frame_decode\n"); +} + +static void +_length_change_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: length_change: %0.3f\n", emotion_object_play_length_get(o)); +} + +static void +_position_update_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: position_update: %0.3f\n", emotion_object_position_get(o)); +} + +static void +_progress_change_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: progress_change: %0.3f, %s\n", + emotion_object_progress_status_get(o), + emotion_object_progress_info_get(o)); +} + +static void +_frame_resize_cb(void *data, Evas_Object *o, void *event_info) +{ + int w, h; + emotion_object_size_get(o, &w, &h); + fprintf(stderr, "smartcb: frame_resize: %dx%d\n", w, h); +} + +static void /* adjust canvas' contents on resizes */ +_canvas_resize_cb(Ecore_Evas *ee) +{ + int w, h; + Evas_Object *bg, *em; + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + + bg = ecore_evas_data_get(ee, "bg"); + em = ecore_evas_data_get(ee, "emotion"); + + evas_object_resize(bg, w, h); + evas_object_move(em, 10, 10); + evas_object_resize(em, w - 20, h - 20); +} + +int +main(int argc, const char *argv[]) +{ + Ecore_Evas *ee; + Evas *e; + Evas_Object *bg, *em; + int i; + + if (argc < 2) + { + printf("One argument is necessary. Usage:\n"); + printf("\t%s \n", argv[0]); + } + + eina_init(); + for (i = 1; i < argc; i++) + filenames = eina_list_append(filenames, eina_stringshare_add(argv[i])); + + curfile = filenames; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL); + if (!ee) + goto error; + + ecore_evas_callback_resize_set(ee, _canvas_resize_cb); + + ecore_evas_show(ee); + + /* the canvas pointer, de facto */ + e = ecore_evas_get(ee); + + /* adding a background to this example */ + bg = evas_object_rectangle_add(e); + evas_object_name_set(bg, "our dear rectangle"); + evas_object_color_set(bg, 255, 0, 0, 255); /* white bg */ + evas_object_move(bg, 0, 0); /* at canvas' origin */ + evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */ + evas_object_show(bg); + + ecore_evas_data_set(ee, "bg", bg); + + /* Creating the emotion object */ + em = _create_emotion_object(e); + emotion_object_file_set(em, eina_list_data_get(curfile)); + evas_object_move(em, 10, 10); + evas_object_resize(em, WIDTH, HEIGHT); + evas_object_resize(em, WIDTH - 20, HEIGHT - 20); + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_BOTH); + emotion_object_bg_color_set(em, 0, 128, 0, 255); + evas_object_show(em); + + ecore_evas_data_set(ee, "emotion", em); + + evas_object_smart_callback_add(em, "frame_decode", _frame_decode_cb, NULL); + evas_object_smart_callback_add(em, "length_change", _length_change_cb, NULL); + evas_object_smart_callback_add(em, "position_update", _position_update_cb, NULL); + evas_object_smart_callback_add(em, "progress_change", _progress_change_cb, NULL); + evas_object_smart_callback_add(em, "frame_resize", _frame_resize_cb, NULL); + + evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, _on_key_down, em); + evas_object_focus_set(bg, EINA_TRUE); + + emotion_object_play_set(em, EINA_TRUE); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + return 0; + +error: + fprintf(stderr, "you got to have at least one evas engine built and linked" + " up to ecore-evas for this example to run properly.\n"); + + EINA_LIST_FREE(filenames, curfile) + eina_stringshare_del(eina_list_data_get(curfile)); + + ecore_evas_shutdown(); + eina_shutdown(); + return -1; +} diff --git a/src/examples/emotion_generic_example.c b/src/examples/emotion_generic_example.c new file mode 100644 index 0000000..b838286 --- /dev/null +++ b/src/examples/emotion_generic_example.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include +#include +#include +#include + +#define WIDTH (320) +#define HEIGHT (240) + +static Eina_List *filenames = NULL; +static Eina_List *curfile = NULL; + +static void +_playback_started_cb(void *data, Evas_Object *o, void *event_info) +{ + printf("Emotion object started playback.\n"); +} + +static void +_playback_stopped_cb(void *data, Evas_Object *o, void *event_info) +{ + printf("Emotion playback stopped.\n"); + emotion_object_play_set(o, EINA_FALSE); + emotion_object_position_set(o, 0); +} + +static Evas_Object * +_create_emotion_object(Evas *e) +{ + Evas_Object *em = emotion_object_add(e); + + emotion_object_init(em, "generic"); + + evas_object_smart_callback_add( + em, "playback_started", _playback_started_cb, NULL); + evas_object_smart_callback_add( + em, "playback_finished", _playback_stopped_cb, NULL); + + return em; +} + +static void +_on_key_down(void *data, Evas *e, Evas_Object *o, void *event_info) +{ + Evas_Event_Key_Down *ev = event_info; + Evas_Object *em = data; + + if (!strcmp(ev->keyname, "Return")) + { + emotion_object_play_set(em, EINA_TRUE); + } + else if (!strcmp(ev->keyname, "space")) + { + emotion_object_play_set(em, EINA_FALSE); + } + else if (!strcmp(ev->keyname, "Escape")) + { + ecore_main_loop_quit(); + } + else if (!strcmp(ev->keyname, "t")) + { + int w, h; + emotion_object_size_get(em, &w, &h); + fprintf(stderr, "example -> size: %dx%d\n", w, h); + } + else if (!strcmp(ev->keyname, "s")) + { + float len, pos; + len = emotion_object_play_length_get(em); + pos = 0.98 * len; + fprintf(stderr, "skipping to position %0.3f\n", pos); + emotion_object_position_set(em, pos); + } + else if (!strcmp(ev->keyname, "1")) + { + fprintf(stderr, "setting speed to 1.0\n"); + emotion_object_play_speed_set(em, 1.0); + } + else if (!strcmp(ev->keyname, "2")) + { + fprintf(stderr, "setting speed to 2.0\n"); + emotion_object_play_speed_set(em, 2.0); + } + else if (!strcmp(ev->keyname, "n")) + { + const char *file; + if (!curfile) + curfile = filenames; + else + curfile = eina_list_next(curfile); + file = eina_list_data_get(curfile); + fprintf(stderr, "playing next file: %s\n", file); + emotion_object_file_set(em, file); + } + else if (!strcmp(ev->keyname, "p")) + { + const char *file; + if (!curfile) + curfile = eina_list_last(filenames); + else + curfile = eina_list_prev(curfile); + file = eina_list_data_get(curfile); + fprintf(stderr, "playing next file: %s\n", file); + emotion_object_file_set(em, file); + } + else if (!strcmp(ev->keyname, "d")) + { + evas_object_del(em); + } + else if (!strcmp(ev->keyname, "l")) + { + // force frame dropping + sleep(5); + } + else + { + fprintf(stderr, "unhandled key: %s\n", ev->keyname); + } +} + +static void +_frame_decode_cb(void *data, Evas_Object *o, void *event_info) +{ + // fprintf(stderr, "smartcb: frame_decode\n"); +} + +static void +_length_change_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: length_change: %0.3f\n", emotion_object_play_length_get(o)); +} + +static void +_position_update_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: position_update: %0.3f\n", emotion_object_position_get(o)); +} + +static void +_progress_change_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: progress_change: %0.3f, %s\n", + emotion_object_progress_status_get(o), + emotion_object_progress_info_get(o)); +} + +static void +_frame_resize_cb(void *data, Evas_Object *o, void *event_info) +{ + int w, h; + emotion_object_size_get(o, &w, &h); + fprintf(stderr, "smartcb: frame_resize: %dx%d\n", w, h); +} + +int +main(int argc, const char *argv[]) +{ + Ecore_Evas *ee; + Evas *e; + Evas_Object *bg, *em; + int i; + + if (argc < 2) + { + printf("One argument is necessary. Usage:\n"); + printf("\t%s \n", argv[0]); + } + + eina_init(); + for (i = 1; i < argc; i++) + filenames = eina_list_append(filenames, eina_stringshare_add(argv[i])); + + curfile = filenames; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL); + if (!ee) + goto error; + + ecore_evas_show(ee); + + /* the canvas pointer, de facto */ + e = ecore_evas_get(ee); + + /* adding a background to this example */ + bg = evas_object_rectangle_add(e); + evas_object_name_set(bg, "our dear rectangle"); + evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */ + evas_object_move(bg, 0, 0); /* at canvas' origin */ + evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */ + evas_object_show(bg); + + /* Creating the emotion object */ + em = _create_emotion_object(e); + emotion_object_file_set(em, eina_list_data_get(curfile)); + evas_object_move(em, 0, 0); + evas_object_resize(em, WIDTH, HEIGHT); + evas_object_show(em); + + evas_object_smart_callback_add(em, "frame_decode", _frame_decode_cb, NULL); + evas_object_smart_callback_add(em, "length_change", _length_change_cb, NULL); + evas_object_smart_callback_add(em, "position_update", _position_update_cb, NULL); + evas_object_smart_callback_add(em, "progress_change", _progress_change_cb, NULL); + evas_object_smart_callback_add(em, "frame_resize", _frame_resize_cb, NULL); + + evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, _on_key_down, em); + evas_object_focus_set(bg, EINA_TRUE); + + emotion_object_play_set(em, EINA_TRUE); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + return 0; + +error: + fprintf(stderr, "you got to have at least one evas engine built and linked" + " up to ecore-evas for this example to run properly.\n"); + + EINA_LIST_FREE(filenames, curfile) + eina_stringshare_del(eina_list_data_get(curfile)); + + ecore_evas_shutdown(); + eina_shutdown(); + return -1; +} diff --git a/src/examples/emotion_signals_example.c b/src/examples/emotion_signals_example.c new file mode 100644 index 0000000..2469c46 --- /dev/null +++ b/src/examples/emotion_signals_example.c @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include + +#define WIDTH (320) +#define HEIGHT (240) + +static void +_display_info(Evas_Object *o) +{ + int w, h; + printf("playing: %d\n", emotion_object_play_get(o)); + printf("meta title: %s\n", + emotion_object_meta_info_get(o, EMOTION_META_INFO_TRACK_TITLE)); + printf("seek position: %0.3f\n", + emotion_object_position_get(o)); + printf("play length: %0.3f\n", + emotion_object_play_length_get(o)); + printf("is seekable: %d\n", + emotion_object_seekable_get(o)); + emotion_object_size_get(o, &w, &h); + printf("video geometry: %dx%d\n", w, h); + printf("video width / height ratio: %0.3f\n", + emotion_object_ratio_get(o)); + printf("\n"); +} + +static void +_playback_started_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object started playback.\n"); + _display_info(o); +} + +static void +_playback_finished_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object finished playback.\n"); + _display_info(o); +} + +static void +_open_done_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object open done.\n"); + _display_info(o); +} + +static void +_position_update_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object first position update.\n"); + evas_object_smart_callback_del(o, "position_update", _position_update_cb); + _display_info(o); +} + +static void +_frame_decode_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object first frame decode.\n"); + evas_object_smart_callback_del(o, "frame_decode", _frame_decode_cb); + _display_info(o); +} + +static void +_decode_stop_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object decode stop.\n"); + _display_info(o); +} + +static void +_frame_resize_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object frame resize.\n"); + _display_info(o); +} + +static void +_setup_emotion_callbacks(Evas_Object *o) +{ + evas_object_smart_callback_add( + o, "playback_started", _playback_started_cb, NULL); + evas_object_smart_callback_add( + o, "playback_finished", _playback_finished_cb, NULL); + evas_object_smart_callback_add( + o, "open_done", _open_done_cb, NULL); + evas_object_smart_callback_add( + o, "position_update", _position_update_cb, NULL); + evas_object_smart_callback_add( + o, "frame_decode", _frame_decode_cb, NULL); + evas_object_smart_callback_add( + o, "decode_stop", _decode_stop_cb, NULL); + evas_object_smart_callback_add( + o, "frame_resize", _frame_resize_cb, NULL); +} + +int +main(int argc, const char *argv[]) +{ + Ecore_Evas *ee; + Evas *e; + Evas_Object *bg, *em; + const char *filename = NULL; + const char *module = NULL; + + if (argc < 2) + { + printf("At least one argument is necessary. Usage:\n"); + printf("\t%s [module_name]\n", argv[0]); + goto error; + } + + filename = argv[1]; + + if (argc >= 3) + module = argv[2]; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL); + if (!ee) + goto error; + + ecore_evas_show(ee); + + /* the canvas pointer, de facto */ + e = ecore_evas_get(ee); + + /* adding a background to this example */ + bg = evas_object_rectangle_add(e); + evas_object_name_set(bg, "our dear rectangle"); + evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */ + evas_object_move(bg, 0, 0); /* at canvas' origin */ + evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */ + evas_object_show(bg); + + /* Creating the emotion object */ + em = emotion_object_add(e); + + /* Try to load the specified module - NULL for auto-discover */ + if (!emotion_object_init(em, module)) + fprintf(stderr, "Emotion: \"%s\" module could not be initialized.\n", module); + + _display_info(em); + _setup_emotion_callbacks(em); + + if (!emotion_object_file_set(em, filename)) + fprintf(stderr, "Emotion: Could not load the file \"%s\"\n", filename); + + evas_object_move(em, 0, 0); + evas_object_resize(em, WIDTH, HEIGHT); + evas_object_show(em); + + emotion_object_play_set(em, EINA_TRUE); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + return 0; + + ecore_evas_free(ee); + +error: + ecore_evas_shutdown(); + return -1; +} diff --git a/src/generic_players/Makefile.am b/src/generic_players/Makefile.am new file mode 100644 index 0000000..bbdd8c3 --- /dev/null +++ b/src/generic_players/Makefile.am @@ -0,0 +1,8 @@ + +MAINTAINERCLEANFILES = Makefile.in + +SUBDIRS = + +if EMOTION_BUILD_GENERIC_VLC +SUBDIRS += vlc +endif diff --git a/src/generic_players/vlc/Makefile.am b/src/generic_players/vlc/Makefile.am new file mode 100644 index 0000000..5cda1b9 --- /dev/null +++ b/src/generic_players/vlc/Makefile.am @@ -0,0 +1,18 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/modules \ +-I$(top_srcdir)/src/modules/generic \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@GENERIC_VLC_CFLAGS@ + +internal_bindir = $(libdir)/emotion/utils +internal_bin_PROGRAMS = em_generic_vlc + +em_generic_vlc_SOURCES = emotion_generic_vlc.c +em_generic_vlc_DEPENDENCIES = $(top_srcdir)/src/modules/generic/Emotion_Generic_Plugin.h +em_generic_vlc_LDADD = @GENERIC_VLC_LIBS@ @EFL_SHM_OPEN_LIBS@ -lpthread diff --git a/src/generic_players/vlc/emotion_generic_vlc.c b/src/generic_players/vlc/emotion_generic_vlc.c new file mode 100644 index 0000000..583036d --- /dev/null +++ b/src/generic_players/vlc/emotion_generic_vlc.c @@ -0,0 +1,873 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +enum _Thread_Events { + EM_THREAD_POSITION_CHANGED, + EM_THREAD_PLAYBACK_STARTED, + EM_THREAD_PLAYBACK_STOPPED, + EM_THREAD_LAST +}; + +struct _App { + Emotion_Generic_Video_Shared *vs; + Emotion_Generic_Video_Frame vf; + libvlc_instance_t *libvlc; + libvlc_media_t *m; + libvlc_media_player_t *mp; + libvlc_event_manager_t *event_mgr; + libvlc_event_manager_t *mevent_mgr; + char *filename; + char *shmname; + void *tmpbuffer; + int w, h; + int fd_read; // read commands from theads here + int fd_write; // write commands from threads here + int em_read; // read commands from emotion here + int em_write; // write commands to emotion here + int size_sent; + int opening; + int closing; + int playing; +}; + +static pthread_mutex_t _mutex_fd = PTHREAD_MUTEX_INITIALIZER; + +int +_em_read_safe(int fd, void *buf, ssize_t size) +{ + ssize_t todo; + char *p; + + todo = size; + p = buf; + + while (todo > 0) + { + ssize_t r; + + r = read(fd, p, todo); + if (r > 0) + { + todo -= r; + p += r; + } + else if (r == 0) + return 0; + else + { + if (errno == EINTR || errno == EAGAIN) + continue; + else + { + fprintf(stderr, "could not read from fd %d: %s", + fd, strerror(errno)); + return 0; + } + } + } + + return 1; +} + +int +_em_write_safe(int fd, const void *buf, ssize_t size) +{ + ssize_t todo; + const char *p; + + todo = size; + p = buf; + + while (todo > 0) + { + ssize_t r; + + r = write(fd, p, todo); + if (r > 0) + { + todo -= r; + p += r; + } + else if (r == 0) + return 0; + else + { + if (errno == EINTR || errno == EAGAIN) + continue; + else + { + fprintf(stderr, "could not write to fd %d: %s", + fd, strerror(errno)); + return 0; + } + } + } + + return 1; +} + +static int +_em_str_read(int fd, char **str) +{ + int size; + int r; + char buf[PATH_MAX]; + + r = _em_read_safe(fd, &size, sizeof(size)); + if (!r) + { + *str = NULL; + return 0; + } + + if (!size) + { + *str = NULL; + return 1; + } + + r = _em_read_safe(fd, buf, size); + if (!r) + { + *str = NULL; + return 0; + } + + *str = strdup(buf); + return 1; +} + +static int +_em_cmd_read(struct _App *app) +{ + int cmd; + _em_read_safe(app->em_read, &cmd, sizeof(cmd)); + + return cmd; +} + +static void +_send_cmd_start(struct _App *app, int cmd) +{ + pthread_mutex_lock(&_mutex_fd); + _em_write_safe(app->em_write, &cmd, sizeof(cmd)); +} + +static void +_send_cmd_finish(struct _App *app __UNUSED__) +{ + pthread_mutex_unlock(&_mutex_fd); +} + +static void +_send_cmd(struct _App *app, int cmd) +{ + _send_cmd_start(app, cmd); + _send_cmd_finish(app); +} + +static void +_send_cmd_str(struct _App *app, const char *str) +{ + int len; + if (str) + len = strlen(str) + 1; + else + len = 0; + _em_write_safe(app->em_write, &len, sizeof(len)); + _em_write_safe(app->em_write, str, len); +} + +#define SEND_CMD_PARAM(app, i) \ + _em_write_safe((app)->em_write, &(i), sizeof((i))); + +static void +_send_resize(struct _App *app, int width, int height) +{ + _send_cmd_start(app, EM_RESULT_FRAME_SIZE); + SEND_CMD_PARAM(app, width); + SEND_CMD_PARAM(app, height); + _send_cmd_finish(app); +} + +static void +_send_length_changed(struct _App *app, const struct libvlc_event_t *ev) +{ + float length = ev->u.media_player_length_changed.new_length; + length /= 1000; + + _send_cmd_start(app, EM_RESULT_LENGTH_CHANGED); + SEND_CMD_PARAM(app, length); + _send_cmd_finish(app); +} + +static void +_send_time_changed(struct _App *app, const struct libvlc_event_t *ev) +{ + float new_time = ev->u.media_player_time_changed.new_time; + new_time /= 1000; + if (app->vs->frame_drop > 1) + return; + _send_cmd_start(app, EM_RESULT_POSITION_CHANGED); + SEND_CMD_PARAM(app, new_time); + _send_cmd_finish(app); +} + +static void +_send_seekable_changed(struct _App *app, const struct libvlc_event_t *ev) +{ + int seekable = ev->u.media_player_seekable_changed.new_seekable; + _send_cmd_start(app, EM_RESULT_SEEKABLE_CHANGED); + SEND_CMD_PARAM(app, seekable); + _send_cmd_finish(app); +} + +static void * +_lock(void *data, void **pixels) +{ + struct _App *app = data; + + if (app->playing) + *pixels = app->vf.frames[app->vs->frame.player]; + else + *pixels = NULL; + + return NULL; // picture identifier, not needed here +} + +static void +_unlock(void *data __UNUSED__, void *id __UNUSED__, void *const *pixels __UNUSED__) +{ +} + +static void +_display(void *data, void *id __UNUSED__) +{ + struct _App *app = data; + if (!app->playing) + return; + + sem_wait(&app->vs->lock); + app->vs->frame.last = app->vs->frame.player; + app->vs->frame.player = app->vs->frame.next; + app->vs->frame.next = app->vs->frame.last; + if (!app->vs->frame_drop++) + _send_cmd(app, EM_RESULT_FRAME_NEW); + sem_post(&app->vs->lock); +} + +static void * +_tmp_lock(void *data, void **pixels) +{ + struct _App *app = data; + *pixels = app->tmpbuffer; + return NULL; +} + +static void +_tmp_unlock(void *data __UNUSED__, void *id __UNUSED__, void *const *pixels __UNUSED__) +{ +} + +static void +_tmp_display(void *data __UNUSED__, void *id __UNUSED__) +{ +} + +static void +_play(struct _App *app) +{ + float pos; + + if (!app->mp) + return; + + _em_read_safe(app->em_read, &pos, sizeof(pos)); + + if (app->playing) + { + libvlc_media_player_set_pause(app->mp, 0); + } + else + { + libvlc_time_t new_time = pos * 1000; + libvlc_media_player_set_time(app->mp, new_time); + libvlc_media_player_play(app->mp); + app->playing = 1; + } +} + +static void +_stop(struct _App *app) +{ + if (app->mp) + libvlc_media_player_set_pause(app->mp, 1); +} + +static void +_send_file_closed(struct _App *app) +{ + app->closing = 0; + emotion_generic_shm_free(app->vs); + _send_cmd(app, EM_RESULT_FILE_CLOSE); +} + +static void +_send_file_set(struct _App *app) +{ + if (app->opening) + _send_cmd(app, EM_RESULT_FILE_SET); + + if (app->closing) + _send_file_closed(app); +} + +static void +_event_cb(const struct libvlc_event_t *ev, void *data) +{ + struct _App *app = data; + int thread_event; + + switch (ev->type) { + case libvlc_MediaPlayerTimeChanged: + _send_time_changed(app, ev); + break; + case libvlc_MediaPlayerPositionChanged: + thread_event = EM_THREAD_POSITION_CHANGED; + write(app->fd_write, &thread_event, sizeof(thread_event)); + break; + case libvlc_MediaPlayerLengthChanged: + _send_length_changed(app, ev); + break; + case libvlc_MediaPlayerSeekableChanged: + _send_seekable_changed(app, ev); + break; + case libvlc_MediaPlayerPlaying: + _send_resize(app, app->w, app->h); + thread_event = EM_THREAD_PLAYBACK_STARTED; + write(app->fd_write, &thread_event, sizeof(thread_event)); + break; + case libvlc_MediaPlayerStopped: + _send_file_set(app); + break; + case libvlc_MediaPlayerEndReached: + thread_event = EM_THREAD_PLAYBACK_STOPPED; + write(app->fd_write, &thread_event, sizeof(thread_event)); + break; + } +} + +static void +_file_set(struct _App *app) +{ + if (app->opening) + { + libvlc_media_release(app->m); + libvlc_media_player_release(app->mp); + free(app->filename); + } + + _em_str_read(app->em_read, &app->filename); + + app->m = libvlc_media_new_path(app->libvlc, app->filename); + if (!app->m) + { + fprintf(stderr, "could not open path: \"%s\"\n", app->filename); + return; + } + + app->mp = libvlc_media_player_new_from_media(app->m); + if (!app->mp) + { + fprintf(stderr, "could not create new player from media.\n"); + return; + } + + app->opening = 1; + libvlc_video_set_format(app->mp, "RV32", DEFAULTWIDTH, DEFAULTHEIGHT, DEFAULTWIDTH * 4); + libvlc_video_set_callbacks(app->mp, _tmp_lock, _tmp_unlock, _tmp_display, app); + app->event_mgr = libvlc_media_player_event_manager(app->mp); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerPositionChanged, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerStopped, + _event_cb, app); + + app->mevent_mgr = libvlc_media_event_manager(app->m); + + app->tmpbuffer = malloc(sizeof(char) * DEFAULTWIDTH * DEFAULTHEIGHT * 4); + libvlc_audio_set_mute(app->mp, 1); + libvlc_media_player_play(app->mp); +} + +static void +_position_set(struct _App *app) +{ + if (!app->mp) + return; + + float position; + _em_read_safe(app->em_read, &position, sizeof(position)); + + libvlc_time_t new_time = position * 1000; + libvlc_media_player_set_time(app->mp, new_time); +} + +static void +_speed_set(struct _App *app) +{ + float rate; + + if (!app->mp) + return; + + _em_read_safe(app->em_read, &rate, sizeof(rate)); + + libvlc_media_player_set_rate(app->mp, rate); +} + +static void +_mute_set(struct _App *app) +{ + int mute; + + if (!app->mp) + return; + + _em_read_safe(app->em_read, &mute, sizeof(mute)); + + libvlc_audio_set_mute(app->mp, mute); +} + +static void +_volume_set(struct _App *app) +{ + float volume; + int vol; + + if (!app->mp) + return; + + _em_read_safe(app->em_read, &volume, sizeof(volume)); + vol = volume * 100; + + libvlc_audio_set_volume(app->mp, vol); +} + +static void +_spu_track_set(struct _App *app) +{ + int track; + + _em_read_safe(app->em_read, &track, sizeof(track)); + + libvlc_video_set_spu(app->mp, track); +} + +static void +_audio_track_set(struct _App *app) +{ + int track; + + _em_read_safe(app->em_read, &track, sizeof(track)); + + libvlc_audio_set_track(app->mp, track); +} + +static void +_video_track_set(struct _App *app) +{ + int track; + + _em_read_safe(app->em_read, &track, sizeof(track)); + + libvlc_video_set_track(app->mp, track); +} + +static void +_file_set_done(struct _App *app) +{ + int r; + + app->opening = 0; + + r = emotion_generic_shm_get(app->shmname, &app->vs, &app->vf); + if (!r) + { + free(app->filename); + libvlc_media_release(app->m); + libvlc_media_player_release(app->mp); + app->filename = NULL; + app->m = NULL; + app->mp = NULL; + _send_cmd_start(app, EM_RESULT_FILE_SET_DONE); + SEND_CMD_PARAM(app, r); + _send_cmd_finish(app); + } + app->w = app->vs->width; + app->h = app->vs->height; + libvlc_video_set_format(app->mp, "RV32", app->w, app->h, app->w * 4); + libvlc_video_set_callbacks(app->mp, _lock, _unlock, _display, app); + + + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerPlaying, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerTimeChanged, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerLengthChanged, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerSeekableChanged, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerEndReached, + _event_cb, app); + + libvlc_audio_set_mute(app->mp, 0); + + _send_cmd_start(app, EM_RESULT_FILE_SET_DONE); + SEND_CMD_PARAM(app, r); + _send_cmd_finish(app); +} + +static void +_file_close(struct _App *app) +{ + app->playing = 0; + if (app->opening) + goto release_resources; + + if (libvlc_media_player_get_state(app->mp) != libvlc_Playing) + { + _send_file_closed(app); + return; + } + + app->closing = 1; + +release_resources: + libvlc_media_player_stop(app->mp); + if (app->filename) + free(app->filename); + if (app->mp) + { + libvlc_media_release(app->m); + libvlc_media_player_release(app->mp); + free(app->tmpbuffer); + } +} + +static void +_process_emotion_commands(struct _App *app) +{ + int cmd = _em_cmd_read(app); + switch (cmd) { + case EM_CMD_FILE_SET: + _file_set(app); + break; + case EM_CMD_FILE_SET_DONE: + _file_set_done(app); + break; + case EM_CMD_FILE_CLOSE: + _file_close(app); + break; + case EM_CMD_PLAY: + _play(app); + break; + case EM_CMD_STOP: + _stop(app); + break; + case EM_CMD_POSITION_SET: + _position_set(app); + break; + case EM_CMD_SPEED_SET: + _speed_set(app); + break; + case EM_CMD_AUDIO_MUTE_SET: + _mute_set(app); + break; + case EM_CMD_VOLUME_SET: + _volume_set(app); + break; + case EM_CMD_SPU_TRACK_SET: + _spu_track_set(app); + break; + case EM_CMD_AUDIO_TRACK_SET: + _audio_track_set(app); + break; + case EM_CMD_VIDEO_TRACK_SET: + _video_track_set(app); + break; + }; +} + +static void +_send_track_info(struct _App *app, int cmd, int current, int count, libvlc_track_description_t *desc) +{ + _send_cmd_start(app, cmd); + SEND_CMD_PARAM(app, current); + SEND_CMD_PARAM(app, count); + while (desc) + { + int tid = desc->i_id; + const char *name = desc->psz_name; + SEND_CMD_PARAM(app, tid); + _send_cmd_str(app, name); + desc = desc->p_next; + } + _send_cmd_finish(app); +} + +static void +_send_all_track_info(struct _App *app) +{ + int track_count, current; + libvlc_track_description_t *desc; + + current = libvlc_audio_get_track(app->mp); + track_count = libvlc_audio_get_track_count(app->mp); + desc = libvlc_audio_get_track_description(app->mp); + + _send_track_info(app, EM_RESULT_AUDIO_TRACK_INFO, + current, track_count, desc); + + current = libvlc_video_get_track(app->mp); + track_count = libvlc_video_get_track_count(app->mp); + desc = libvlc_video_get_track_description(app->mp); + + _send_track_info(app, EM_RESULT_VIDEO_TRACK_INFO, + current, track_count, desc); + + current = libvlc_video_get_spu(app->mp); + track_count = libvlc_video_get_spu_count(app->mp); + desc = libvlc_video_get_spu_description(app->mp); + + _send_track_info(app, EM_RESULT_SPU_TRACK_INFO, + current, track_count, desc); +} + +static void +_send_all_meta_info(struct _App *app) +{ + const char *meta; + + _send_cmd_start(app, EM_RESULT_META_INFO); + + /* + * Will send in this order: title, artist, album, year, + * genre, comments, disc id and track count. + */ + meta = libvlc_media_get_meta(app->m, libvlc_meta_Title); + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_Artist); + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_Album); + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_Date); + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_Genre); + _send_cmd_str(app, meta); + meta = NULL; // sending empty comments + _send_cmd_str(app, meta); + meta = NULL; // sending empty disc id + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_TrackNumber); + _send_cmd_str(app, meta); + _send_cmd_finish(app); +} + +static void +_position_changed(struct _App *app) +{ + if (!app->opening) + return; + + /* sending size info only once */ + int r; + unsigned int w, h; + r = libvlc_video_get_size(app->mp, 0, &w, &h); + if (r < 0) + { + w = 1; + h = 1; + } + _send_resize(app, w, h); + + /* sending audio track info */ + _send_all_track_info(app); + + /* sending meta info */ + _send_all_meta_info(app); + + libvlc_media_player_stop(app->mp); +} + +static void +_process_thread_events(struct _App *app) +{ + int event; + size_t size; + + size = read(app->fd_read, &event, sizeof(event)); + if (size != sizeof(event)) + { + fprintf(stderr, "player: problem when reading thread event. size = %zd\n", size); + return; + } + + switch (event) { + case EM_THREAD_POSITION_CHANGED: + _position_changed(app); + break; + case EM_THREAD_PLAYBACK_STARTED: + _send_cmd(app, EM_RESULT_PLAYBACK_STARTED); + break; + case EM_THREAD_PLAYBACK_STOPPED: + app->playing = 0; + _send_cmd(app, EM_RESULT_PLAYBACK_STOPPED); + break; + } +} + +int +main(int argc, const char *argv[]) +{ + struct _App app; + struct pollfd fds[3]; + int tpipe[2]; // pipe for comunicating events from threads + char cwidth[64], cheight[64], cpitch[64], chroma[64]; + char buf[64]; + const char *vlc_argv[] = + { + "--quiet", + "--vout", + "vmem", + "--vmem-width", + cwidth, + "--vmem-height", + cheight, + "--vmem-pitch", + cpitch, + "--vmem-chroma", + chroma + }; + + if (argc < 3) + { + fprintf(stderr, "player: missing paramters.\n"); + fprintf(stderr, "syntax:\n\t%s \n", argv[0]); + return -1; + } + + app.em_read = atoi(argv[1]); + app.em_write = atoi(argv[2]); + + int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv); + snprintf(cwidth, sizeof(cwidth), "%d", DEFAULTWIDTH); + snprintf(cheight, sizeof(cheight), "%d", DEFAULTHEIGHT); + snprintf(cpitch, sizeof(cpitch), "%d", DEFAULTWIDTH * 4); + snprintf(chroma, sizeof(chroma), "RV32"); + + /* + * Naughty xattr in emotion uses ecore_thread to run its thing, this + * may leave emotion's reference count high and it won't kill us... + * letting us play the video in the background. not good. + * + * prctl(PR_SET_PDEATHSIG) is a linux only thing. Need to find ways + * to do it on other platforms. Until then leave it breaking on + * such platforms so people port it instead of ignoring. + */ + prctl(PR_SET_PDEATHSIG, SIGHUP); + + app.libvlc = libvlc_new(vlc_argc, vlc_argv); + app.mp = NULL; + app.filename = NULL; + app.w = 0; + app.h = 0; + app.size_sent = 0; + app.opening = 0; + app.playing = 0; + app.closing = 0; + + if (_em_cmd_read(&app) != EM_CMD_INIT) + { + fprintf(stderr, "player: wrong init command!\n"); + return -1; + } + + int size; + _em_read_safe(app.em_read, &size, sizeof(size)); + _em_read_safe(app.em_read, buf, size); + app.shmname = strdup(buf); + + _send_cmd(&app, EM_RESULT_INIT); + + pipe(tpipe); + app.fd_read = tpipe[0]; + app.fd_write = tpipe[1]; + fds[0].fd = app.em_read; + fds[0].events = POLLIN; + fds[1].fd = app.fd_read; + fds[1].events = POLLIN; + fds[2].fd = STDERR_FILENO; + fds[2].events = 0; + + while (1) + { + int r; + + r = poll(fds, 3, -1); + if (r == 0) + continue; + else if (r < 0) + { + fprintf(stderr, + "emotion_generic_vlc: an error ocurred on poll(): %s\n", + strerror(errno)); + break; + } + + if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) + { + fputs("emotion_generic_vlc: error communicating with stdin\n", + stderr); + break; + } + if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) + { + fputs("emotion_generic_vlc: error communicating with thread\n", + stderr); + break; + } + + if (fds[0].revents & POLLIN) + _process_emotion_commands(&app); + if (fds[1].revents & POLLIN) + _process_thread_events(&app); + if (fds[2].revents & (POLLERR | POLLHUP | POLLNVAL)) + break; + } + + libvlc_release(app.libvlc); + + + return 0; +} +#undef SEND_CMD_PARAM diff --git a/src/lib/Emotion.h b/src/lib/Emotion.h new file mode 100644 index 0000000..da5c85c --- /dev/null +++ b/src/lib/Emotion.h @@ -0,0 +1,1282 @@ +#ifndef EMOTION_H +#define EMOTION_H + +/** + * @file + * @brief Emotion Media Library + * + * These routines are used for Emotion. + */ + +/** + * + * @mainpage Emotion Library Documentation + * + * @version 1.7.0 + * @date 2003-2012 + * + * @section intro What is Emotion? + * + * A media object library for Evas and Ecore. + * + * Emotion is a library that allows playing audio and video files, using one of + * its backends (gstreamer or xine). + * + * It is integrated into Ecore through its mainloop, and is transparent to the + * user of the library how the decoding of audio and video is being done. Once + * the objects are created, the user can set callbacks to the specific events + * and set options to this object, all in the main loop (no threads are needed). + * + * Emotion is also integrated with Evas. The emotion object returned by + * emotion_object_add() is an Evas smart object, so it can be manipulated with + * default Evas object functions. Callbacks can be added to the signals emitted + * by this object with evas_object_smart_callback_add(). + * + * @section work How does Emotion work? + * + * The Emotion library uses Evas smart objects to allow you to manipulate the + * created object as any other Evas object, and to connect to its signals, + * handling them when needed. It's also possible to swallow Emotion objects + * inside Edje themes, and expect it to behave as a normal image or rectangle + * when regarding to its dimensions. + * + * To instantiate an Emotion object, the simple code below is enough: + * + * @code + * em = emotion_object_add(e); + * emotion_object_init(em, NULL); + * + * emotion_object_file_set(em, file_path); + * + * evas_object_move(em, 0, 0); + * evas_object_resize(em, WIDTH, HEIGHT); + * evas_object_show(em); + * + * emotion_object_play_set(em, EINA_TRUE); + * @endcode + * + * See the @ref Emotion_API for a better reference. + * + * Please see the @ref authors page for contact details. + * + */ + +/** + * + * @page authors Authors + * + * @author Carsten Haitzler + * @author Vincent Torri + * @author Nicolas Aguirre + * @author Sebastian Dransfeld + * @author Cedric Bail + * + * Please contact to get in + * contact with the developers and maintainers. + * + */ + +#include + +#ifdef EAPI +# undef EAPI +#endif + +#ifdef _WIN32 +# ifdef EFL_EMOTION_BUILD +# ifdef DLL_EXPORT +# define EAPI __declspec(dllexport) +# else +# define EAPI +# endif /* ! DLL_EXPORT */ +# else +# define EAPI __declspec(dllimport) +# endif /* ! EFL_EMOTION_BUILD */ +#else +# ifdef __GNUC__ +# if __GNUC__ >= 4 +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +# else +# define EAPI +# endif +#endif /* ! _WIN32 */ + +/** + * @file Emotion.h + * @brief The file that provides Emotion the API, with functions available for + * play, seek, change volume, etc. + */ + +enum _Emotion_Module +{ + EMOTION_MODULE_XINE, + EMOTION_MODULE_GSTREAMER +}; + +enum _Emotion_Event +{ + EMOTION_EVENT_MENU1, // Escape Menu + EMOTION_EVENT_MENU2, // Title Menu + EMOTION_EVENT_MENU3, // Root Menu + EMOTION_EVENT_MENU4, // Subpicture Menu + EMOTION_EVENT_MENU5, // Audio Menu + EMOTION_EVENT_MENU6, // Angle Menu + EMOTION_EVENT_MENU7, // Part Menu + EMOTION_EVENT_UP, + EMOTION_EVENT_DOWN, + EMOTION_EVENT_LEFT, + EMOTION_EVENT_RIGHT, + EMOTION_EVENT_SELECT, + EMOTION_EVENT_NEXT, + EMOTION_EVENT_PREV, + EMOTION_EVENT_ANGLE_NEXT, + EMOTION_EVENT_ANGLE_PREV, + EMOTION_EVENT_FORCE, + EMOTION_EVENT_0, + EMOTION_EVENT_1, + EMOTION_EVENT_2, + EMOTION_EVENT_3, + EMOTION_EVENT_4, + EMOTION_EVENT_5, + EMOTION_EVENT_6, + EMOTION_EVENT_7, + EMOTION_EVENT_8, + EMOTION_EVENT_9, + EMOTION_EVENT_10 +}; + +/** + * @enum _Emotion_Meta_Info + * + * Used for retrieving information about the media file being played. + * + * @see emotion_object_meta_info_get() + * + * @ingroup Emotion_Info + */ +enum _Emotion_Meta_Info +{ + EMOTION_META_INFO_TRACK_TITLE, /**< track title */ + EMOTION_META_INFO_TRACK_ARTIST, /**< artist name */ + EMOTION_META_INFO_TRACK_ALBUM, /**< album name */ + EMOTION_META_INFO_TRACK_YEAR, /**< track year */ + EMOTION_META_INFO_TRACK_GENRE, /**< track genre */ + EMOTION_META_INFO_TRACK_COMMENT, /**< track comments */ + EMOTION_META_INFO_TRACK_DISC_ID, /**< track disc ID */ + EMOTION_META_INFO_TRACK_COUNT /**< track count - number of the track in the album */ +}; + +/** + * @enum _Emotion_Vis + * + * Used for displaying a visualization on the emotion object. + * + * @see emotion_object_vis_set() + * + * @ingroup Emotion_Visualization + */ +enum _Emotion_Vis +{ + EMOTION_VIS_NONE, /**< no visualization set */ + EMOTION_VIS_GOOM, /**< goom */ + EMOTION_VIS_LIBVISUAL_BUMPSCOPE, /**< bumpscope */ + EMOTION_VIS_LIBVISUAL_CORONA, /**< corona */ + EMOTION_VIS_LIBVISUAL_DANCING_PARTICLES, /**< dancing particles */ + EMOTION_VIS_LIBVISUAL_GDKPIXBUF, /**< gdkpixbuf */ + EMOTION_VIS_LIBVISUAL_G_FORCE, /**< G force */ + EMOTION_VIS_LIBVISUAL_GOOM, /**< goom */ + EMOTION_VIS_LIBVISUAL_INFINITE, /**< infinite */ + EMOTION_VIS_LIBVISUAL_JAKDAW, /**< jakdaw */ + EMOTION_VIS_LIBVISUAL_JESS, /**< jess */ + EMOTION_VIS_LIBVISUAL_LV_ANALYSER, /**< lv analyser */ + EMOTION_VIS_LIBVISUAL_LV_FLOWER, /**< lv flower */ + EMOTION_VIS_LIBVISUAL_LV_GLTEST, /**< lv gltest */ + EMOTION_VIS_LIBVISUAL_LV_SCOPE, /**< lv scope */ + EMOTION_VIS_LIBVISUAL_MADSPIN, /**< madspin */ + EMOTION_VIS_LIBVISUAL_NEBULUS, /**< nebulus */ + EMOTION_VIS_LIBVISUAL_OINKSIE, /**< oinksie */ + EMOTION_VIS_LIBVISUAL_PLASMA, /**< plasma */ + EMOTION_VIS_LAST /* sentinel */ +}; + +/** + * @enum Emotion_Suspend + * + * Used for emotion pipeline ressource management. + * + * @see emotion_object_suspend_set() + * @see emotion_object_suspend_get() + * + * @ingroup Emotion_Ressource + */ +typedef enum +{ + EMOTION_WAKEUP, /**< pipeline is up and running */ + EMOTION_SLEEP, /**< turn off hardware ressource usage like overlay */ + EMOTION_DEEP_SLEEP, /**< destroy the pipeline, but keep full resolution pixels output around */ + EMOTION_HIBERNATE /**< destroy the pipeline, and keep half resolution or object resolution if lower */ +} Emotion_Suspend; + +/** + * @enum _Emotion_Aspect + * Defines the aspect ratio option. + */ +enum _Emotion_Aspect +{ + EMOTION_ASPECT_KEEP_NONE, /**< ignore video aspect ratio */ + EMOTION_ASPECT_KEEP_WIDTH, /**< respect video aspect, fitting its width inside the object width */ + EMOTION_ASPECT_KEEP_HEIGHT, /**< respect video aspect, fitting its height inside the object height */ + EMOTION_ASPECT_KEEP_BOTH, /**< respect video aspect, fitting it inside the object area */ + EMOTION_ASPECT_CROP, /**< respect video aspect, cropping exceding area */ + EMOTION_ASPECT_CUSTOM, /**< use custom borders/crop for the video */ +}; + +typedef enum _Emotion_Module Emotion_Module; +typedef enum _Emotion_Event Emotion_Event; +typedef enum _Emotion_Meta_Info Emotion_Meta_Info; /**< Meta info type to be retrieved. */ +typedef enum _Emotion_Vis Emotion_Vis; /**< Type of visualization. */ +typedef enum _Emotion_Aspect Emotion_Aspect; /**< Aspect ratio option. */ + +#define EMOTION_CHANNEL_AUTO -1 +#define EMOTION_CHANNEL_DEFAULT 0 + +#ifdef __cplusplus +extern "C" { +#endif + +#define EMOTION_VERSION_MAJOR 1 +#define EMOTION_VERSION_MINOR 7 + + typedef struct _Emotion_Version + { + int major; + int minor; + int micro; + int revision; + } Emotion_Version; + + EAPI extern Emotion_Version *emotion_version; + +/* api calls available */ + +/** + * @brief How to create, initialize, manipulate and connect to signals of an + * Emotion object. + * @defgroup Emotion_API API available for manipulating Emotion object. + * + * @{ + * + * Emotion provides an Evas smart object that allows to play, control and + * display a video or audio file. The API is synchronous but not everything + * happens immediately. There are also some signals to report changed states. + * + * Basically, once the object is created and initialized, a file will be set to + * it, and then it can be resized, moved, and controlled by other Evas object + * functions. + * + * However, the decoding of the music and video occurs not in the Ecore main + * loop, but usually in another thread (this depends on the module being used). + * The synchronization between this other thread and the main loop not visible + * to the end user of the library. The user can just register callbacks to the + * available signals to receive information about the changed states, and can + * call other functions from the API to request more changes on the current + * loaded file. + * + * There will be a delay between an API being called and it being really + * executed, since this request will be done in the main thread, and it needs to + * be sent to the decoding thread. For this reason, always call functions like + * emotion_object_size_get() or emotion_object_length_get() after some signal + * being sent, like "playback_started" or "open_done". @ref + * emotion_signals_example.c "This example demonstrates this behavior". + * + * @section signals Available signals + * The Evas_Object returned by emotion_object_add() has a number of signals that + * can be listened to using evas' smart callbacks mechanism. All signals have + * NULL as event info. The following is a list of interesting signals: + * @li "playback_started" - Emitted when the playback starts + * @li "playback_finished" - Emitted when the playback finishes + * @li "frame_decode" - Emitted every time a frame is decoded + * @li "open_done" - Emitted when the media file is opened + * @li "position_update" - Emitted when emotion_object_position_set is called + * @li "decode_stop" - Emitted after the last frame is decoded + * + * @section Examples + * + * The following examples exemplify the emotion usage. There's also the + * emotion_test binary that is distributed with this library and cover the + * entire API, but since it is too long and repetitive to be explained, its code + * is just displayed as another example. + * + * @li @ref emotion_basic_example_c + * @li @ref emotion_signals_example.c "Emotion signals" + * @li @ref emotion_test_main.c "emotion_test - full API usage" + * + */ + +/** + * @defgroup Emotion_Init Creation and initialization functions + */ + +/** + * @defgroup Emotion_Audio Audio control functions + */ + +/** + * @defgroup Emotion_Video Video control functions + */ + +/** + * @defgroup Emotion_Visualization Visualization control functions + */ + +/** + * @defgroup Emotion_Info Miscellaneous information retrieval functions + */ + +/** + * @defgroup Emotion_Ressource Video ressource management + */ + +EAPI Eina_Bool emotion_init(void); +EAPI Eina_Bool emotion_shutdown(void); + +/** + * @brief Add an emotion object to the canvas. + * + * @param evas The canvas where the object will be added to. + * @return The emotion object just created. + * + * This function creates an emotion object and adds it to the specified @p evas. + * The returned object can be manipulated as any other Evas object, using the + * default object manipulation functions - evas_object_*. + * + * After creating the object with this function, it's still necessary to + * initialize it with emotion_object_init(), and if an audio file is going to be + * played with this object instead of a video, use + * emotion_object_video_mute_set(). + * + * The next step is to open the desired file with emotion_object_file_set(), and + * start playing it with emotion_object_play_set(). + * + * @see emotion_object_init() + * @see emotion_object_video_mute_set() + * @see emotion_object_file_set() + * @see emotion_object_play_set() + * + * @ingroup Emotion_Init + */ +EAPI Evas_Object *emotion_object_add (Evas *evas); + +/** + * @brief Set the specified option for the current module. + * + * @param obj The emotion object which the option is being set to. + * @param opt The option that is being set. Currently supported optiosn: "video" + * and "audio". + * @param val The value of the option. Currently only supports "off" (?!?!?!) + * + * This function allows one to mute the video or audio of the emotion object. + * + * @note Please don't use this function, consider using + * emotion_object_audio_mute_set() and emotion_object_video_mute_set() instead. + * + * @see emotion_object_audio_mute_set() + * @see emotion_object_video_mute_set() + * + * @ingroup Emotion_Init + */ +EAPI void emotion_object_module_option_set (Evas_Object *obj, const char *opt, const char *val); + +/** + * @brief Initializes an emotion object with the specified module. + * + * @param obj The emotion object to be initialized. + * @param module_filename The name of the module to be used (gstreamer or xine). + * @return @c EINA_TRUE if the specified module was successfully initialized for + * this object, @c EINA_FALSE otherwise. + * + * This function is required after creating the emotion object, in order to + * specify which module will be used with this object. Different objects can + * use different modules to play a media file. The current supported modules are + * @b gstreamer and @b xine. + * + * To use any of them, you need to make sure that support for them was compiled + * correctly. + * + * @note It's possible to disable the build of a module with + * --disable-module_name. + * + * @see emotion_object_add() + * @see emotion_object_file_set() + * + * @ingroup Emotion_Init + */ +EAPI Eina_Bool emotion_object_init (Evas_Object *obj, const char *module_filename); + +/** + * @brief Set borders for the emotion object. + * + * @param obj The emotion object where borders are being set. + * @param l The left border. + * @param r The right border. + * @param t The top border. + * @param b The bottom border. + * + * This function sets borders for the emotion video object (just when a video is + * present). When positive values are given to one of the parameters, a border + * will be added to the respective position of the object, representing that + * size on the original video size. However, if the video is scaled up or down + * (i.e. the emotion object size is different from the video size), the borders + * will be scaled respectively too. + * + * If a negative value is given to one of the parameters, instead of a border, + * that respective side of the video will be cropped. + * + * It's possible to set a color for the added borders (default is transparent) + * with emotion_object_bg_color_set(). By default, an Emotion object doesn't + * have any border. + * + * @see emotion_object_border_get() + * @see emotion_object_bg_color_set() + * + * @ingroup Emotion_Video + */ +EAPI void emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b); + +/** + * @brief Get the borders set for the emotion object. + * + * @param obj The emotion object from which the borders are being retrieved. + * @param l The left border. + * @param r The right border. + * @param t The top border. + * @param b The bottom border. + * + * @see emotion_object_border_set() + * + * @ingroup Emotion_Video + */ +EAPI void emotion_object_border_get(const Evas_Object *obj, int *l, int *r, int *t, int *b); + +/** + * @brief Set a color for the background rectangle of this emotion object. + * + * @param obj The emotion object where the background color is being set. + * @param r Red component of the color. + * @param g Green component of the color. + * @param b Blue component of the color. + * @param a Alpha channel of the color. + * + * This is useful when a border is added to any side of the Emotion object. The + * area between the edge of the video and the edge of the object will be filled + * with the specified color. + * + * The default color is 0, 0, 0, 0 (transparent). + * + * @see emotion_object_bg_color_get() + * + * @ingroup Emotion_Video + */ +EAPI void emotion_object_bg_color_set(Evas_Object *obj, int r, int g, int b, int a); + +/** + * @brief Get the background color set for the emotion object. + * + * @param obj The emotion object from which the background color is being retrieved. + * @param r Red component of the color. + * @param g Green component of the color. + * @param b Blue component of the color. + * @param a AAlpha channel of the color. + * + * @see emotion_object_bg_color_set() + * + * @ingroup Emotion_Video + */ +EAPI void emotion_object_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a); + +/** + * @brief Set whether emotion should keep the aspect ratio of the video. + * + * @param obj The emotion object where to set the aspect. + * @param a The aspect ratio policy. + * + * Instead of manually calculating the required border to set with + * emotion_object_border_set(), and using this to fix the aspect ratio of the + * video when the emotion object has a different aspect, it's possible to just + * set the policy to be used. + * + * The options are: + * + * - @b #EMOTION_ASPECT_KEEP_NONE - ignore the video aspect ratio, and reset any + * border set to 0, stretching the video inside the emotion object area. This + * option is similar to EVAS_ASPECT_CONTROL_NONE size hint. + * - @b #EMOTION_ASPECT_KEEP_WIDTH - respect the video aspect ratio, fitting the + * video width inside the object width. This option is similar to + * EVAS_ASPECT_CONTROL_HORIZONTAL size hint. + * - @b #EMOTION_ASPECT_KEEP_HEIGHT - respect the video aspect ratio, fitting + * the video height inside the object height. This option is similar to + * EVAS_ASPECT_CONTROL_VERTIAL size hint. + * - @b #EMOTION_ASPECT_KEEP_BOTH - respect the video aspect ratio, fitting both + * its width and height inside the object area. This option is similar to + * EVAS_ASPECT_CONTROL_BOTH size hint. It's the effect called letterboxing. + * - @b #EMOTION_ASPECT_CROP - respect the video aspect ratio, fitting the width + * or height inside the object area, and cropping the exceding areas of the + * video in height or width. It's the effect called pan-and-scan. + * - @b #EMOTION_ASPECT_CUSTOM - ignore the video aspect ratio, and use the + * current set from emotion_object_border_set(). + * + * @note Calling this function with any value except #EMOTION_ASPECT_CUSTOM will + * invalidate borders set with emotion_object_border_set(). + * + * @note Calling emotion_object_border_set() will automatically set the aspect + * policy to #EMOTION_ASPECT_CUSTOM. + * + * @see emotion_object_border_set() + * @see emotion_object_keep_aspect_get() + * + * @ingroup Emotion_Video + */ +EAPI void emotion_object_keep_aspect_set(Evas_Object *obj, Emotion_Aspect a); + +/** + * @brief Get the current emotion aspect ratio policy. + * + * @param obj The emotion object from which we are fetching the aspect ratio + * policy. + * @return The current aspect ratio policy. + * + * @see emotion_object_keep_aspect_set() + * + * @ingroup Emotion_Video + */ +EAPI Emotion_Aspect emotion_object_keep_aspect_get(const Evas_Object *obj); + +/** + * @brief Set the file to be played in the Emotion object. + * + * @param obj The emotion object where the file is being loaded. + * @param filename Path to the file to be loaded. It can be absolute or relative + * path. + * @return EINA_TRUE if the new file could be loaded successfully, and + * EINA_FALSE if the file could not be loaded. This happens when the filename is + * could not be found, when the module couldn't open the file, when no module is + * initialized in this object, or when the @p filename is the same as the + * one previously set. + * + * This function sets the file to be used with this emotion object. If the + * object already has another file set, this file will be unset and unloaded, + * and the new file will be loaded to this emotion object. The seek position + * will be set to 0, and the emotion object will be paused, instead of playing. + * + * If there was already a filename set, and it's the same as the one being set + * now, this function does nothing and returns EINA_FALSE. + * + * Use @c NULL as argument to @p filename if you want to unload the current file + * but don't want to load anything else. + * + * @see emotion_object_init() + * @see emotion_object_play_set() + * @see emotion_object_file_get() + * + * @ingroup Emotion_Init + */ +EAPI Eina_Bool emotion_object_file_set (Evas_Object *obj, const char *filename); + +/** + * @brief Get the filename of the file associated with the emotion object. + * + * @param obj The emotion object from which the filename will be retrieved. + * @return The path to the file loaded into this emotion object. + * + * This function returns the path of the file loaded in this emotion object. If + * no object is loaded, it will return @c NULL. + * + * @note Don't free or change the string returned by this function in any way. + * If you want to unset it, use @c emotion_object_file_set(obj, NULL). + * + * @see emotion_object_file_set() + * + * @ingroup Emotion_Init + */ +EAPI const char *emotion_object_file_get (const Evas_Object *obj); +/** + * @defgroup Emotion_Play Play control functions + * + * @{ + */ +/** + * + * @brief Set play/pause state of the media file. + * + * @param obj The emotion object whose state will be changed. + * @param play EINA_TRUE to play, EINA_FALSE to pause. + * + * This functions sets the currently playing status of the video. Using this + * function to play or pause the video doesn't alter it's current position. + */ +EAPI void emotion_object_play_set (Evas_Object *obj, Eina_Bool play); +/** + * @brief Get play/pause state of the media file. + * + * @param obj The emotion object from which the state will be retrieved. + * @return EINA_TRUE if playing. EINA_FALSE if not playing. + */ +EAPI Eina_Bool emotion_object_play_get (const Evas_Object *obj); +/** + * @brief Set the position in the media file. + * + * @param obj The emotion object whose position will be changed. + * @param sec The position(in seconds) to which the media file will be set. + * + * This functions sets the current position of the media file to @p sec, this + * only works on seekable streams. Setting the position doesn't change the + * playing state of the media file. + * + * @see emotion_object_seekable_get + */ +EAPI void emotion_object_position_set (Evas_Object *obj, double sec); +/** + * @brief Get the position in the media file. + * + * @param obj The emotion object from which the position will be retrieved. + * @return The position of the media file. + * + * The position is returned as the number of seconds since the beginning of the + * media file. + */ +EAPI double emotion_object_position_get (const Evas_Object *obj); + +/** + * @brief Get the percentual size of the buffering cache. + * + * @param obj The emotion object from which the buffer size will be retrieved. + * @return The buffer percent size, ranging from 0.0 to 1.0 + * + * The buffer size is returned as a number between 0.0 and 1.0, 0.0 means + * the buffer if empty, 1.0 means full. + * If no buffering is in progress 1.0 is returned. In all other cases (maybe + * the backend don't support buffering) 1.0 is returned, thus you can always + * check for buffer_size < 1.0 to know if buffering is in progress. + * + * @warning Generic backend don't implement this (will return 1.0). + */ +EAPI double emotion_object_buffer_size_get (const Evas_Object *obj); + +/** + * @brief Get whether the media file is seekable. + * + * @param obj The emotion object from which the seekable status will be + * retrieved. + * @return EINA_TRUE if the media file is seekable, EINA_FALSE otherwise. + */ +EAPI Eina_Bool emotion_object_seekable_get (const Evas_Object *obj); +/** + * @brief Get the length of play for the media file. + * + * @param obj The emotion object from which the length will be retrieved. + * @return The length of the media file in seconds. + * + * This function returns the length of the media file in seconds. + * + * @warning This will return 0 if called before the "length_change" signal has, + * been emitted. + */ +EAPI double emotion_object_play_length_get (const Evas_Object *obj); + +/** + * @brief Set the play speed of the media file. + * + * @param obj The emotion object whose speed will be set. + * @param speed The speed to be set in the range [0,infinity) + * + * This function sets the speed with which the media file will be played. 1.0 + * represents the normal speed, 2 double speed, 0.5 half speed and so on. + * + * @warning The only backend that implements this is the experimental VLC + * backend. + */ +EAPI void emotion_object_play_speed_set (Evas_Object *obj, double speed); +/** + * @brief Get the play speed of the media file. + * + * @param obj The emotion object from which the filename will be retrieved. + * @return The current speed of the media file. + * + * @see emotion_object_play_speed_set + */ +EAPI double emotion_object_play_speed_get (const Evas_Object *obj); +/** + * @brief Get how much of the file has been played. + * + * @param obj The emotion object from which the filename will be retrieved. + * @return The progress of the media file. + * + * @warning Don't change of free the returned string. + * @warning gstreamer xine backends don't implement this(will return NULL). + */ +EAPI const char *emotion_object_progress_info_get (const Evas_Object *obj); +/** + * @brief Get how much of the file has been played. + * + * @param obj The emotion object from which the filename will be retrieved + * @return The progress of the media file. + * + * This function gets the progress in playing the file, the return value is in + * the [0, 1] range. + * + * @warning gstreamer xine backends don't implement this(will return 0). + */ +EAPI double emotion_object_progress_status_get (const Evas_Object *obj); +/** + * @} + */ +EAPI Eina_Bool emotion_object_video_handled_get (const Evas_Object *obj); +EAPI Eina_Bool emotion_object_audio_handled_get (const Evas_Object *obj); + +/** + * @brief Retrieve the video aspect ratio of the media file loaded. + * + * @param obj The emotion object which the video aspect ratio will be retrieved + * from. + * @return The video aspect ratio of the file loaded. + * + * This function returns the video aspect ratio (width / height) of the file + * loaded. It can be used to adapt the size of the emotion object in the canvas, + * so the aspect won't be changed (by wrongly resizing the object). Or to crop + * the video correctly, if necessary. + * + * The described behavior can be applied like following. Consider a given + * emotion object that we want to position inside an area, which we will + * represent by @c w and @c h. Since we want to position this object either + * stretching, or filling the entire area but overflowing the video, or just + * adjust the video to fit inside the area without keeping the aspect ratio, we + * must compare the video aspect ratio with the area aspect ratio: + * @code + * int w = 200, h = 300; // an arbitrary value which represents the area where + * // the video would be placed + * int vw, vh; + * double r, vr = emotion_object_ratio_get(obj); + * r = (double)w / h; + * @endcode + * + * Now, if we want to make the video fit inside the area, the following code + * would do it: + * @code + * if (vr > r) // the video is wider than the area + * { + * vw = w; + * vh = w / vr; + * } + * else // the video is taller than the area + * { + * vh = h; + * vw = h * vr; + * } + * evas_object_resize(obj, vw, vh); + * @endcode + * + * And for keeping the aspect ratio but making the video fill the entire area, + * overflowing the content which can't fit inside it, we would do: + * @code + * if (vr > r) // the video is wider than the area + * { + * vh = h; + * vw = h * vr; + * } + * else // the video is taller than the area + * { + * vw = w; + * vh = w / vr; + * } + * evas_object_resize(obj, vw, vh); + * @endcode + * + * Finally, by just resizing the video to the video area, we would have the + * video stretched: + * @code + * vw = w; + * vh = h; + * evas_object_resize(obj, vw, vh); + * @endcode + * + * The following diagram exemplifies what would happen to the video, + * respectively, in each case: + * + * @image html emotion_ratio.png + * @image latex emotion_ratio.eps width=\textwidth + * + * @note This function returns the aspect ratio that the video @b should be, but + * sometimes the reported size from emotion_object_size_get() represents a + * different aspect ratio. You can safely resize the video to respect the aspect + * ratio returned by @b this function. + * + * @see emotion_object_size_get() + * + * @ingroup Emotion_Video + */ +EAPI double emotion_object_ratio_get (const Evas_Object *obj); + +/** + * @brief Retrieve the video size of the loaded file. + * + * @param obj The object from which we are retrieving the video size. + * @param iw A pointer to a variable where the width will be stored. + * @param ih A pointer to a variable where the height will be stored. + * + * This function returns the reported size of the loaded video file. If a file + * that doesn't contain a video channel is loaded, then this size can be + * ignored. + * + * The value reported by this function should be consistent with the aspect + * ratio returned by emotion_object_ratio_get(), but sometimes the information + * stored in the file is wrong. So use the ratio size reported by + * emotion_object_ratio_get(), since it is more likely going to be accurate. + * + * @note Use @c NULL for @p iw or @p ih if you don't need one of these values. + * + * @see emotion_object_ratio_get() + * + * @ingroup Emotion_Video + */ +EAPI void emotion_object_size_get (const Evas_Object *obj, int *iw, int *ih); + +/** + * @brief Sets whether to use of high-quality image scaling algorithm + * of the given video object. + * + * When enabled, a higher quality video scaling algorithm is used when + * scaling videos to sizes other than the source video. This gives + * better results but is more computationally expensive. + * + * @param obj The given video object. + * @param smooth Whether to use smooth scale or not. + * + * @see emotion_object_smooth_scale_get() + * + * @ingroup Emotion_Video + */ +EAPI void emotion_object_smooth_scale_set (Evas_Object *obj, Eina_Bool smooth); + +/** + * @brief Gets whether the high-quality image scaling algorithm + * of the given video object is used. + * + * @param obj The given video object. + * @return Whether the smooth scale is used or not. + * + * @see emotion_object_smooth_scale_set() + * + * @ingroup Emotion_Video + */ +EAPI Eina_Bool emotion_object_smooth_scale_get (const Evas_Object *obj); +EAPI void emotion_object_event_simple_send (Evas_Object *obj, Emotion_Event ev); + +/** + * @brief Set the audio volume. + * + * @param obj The object where the volume is being set. + * @param vol The new volume parameter. Range is from 0.0 to 1.0. + * + * Sets the audio volume of the stream being played. This has nothing to do with + * the system volume. This volume will be multiplied by the system volume. e.g.: + * if the current volume level is 0.5, and the system volume is 50%, it will be + * 0.5 * 0.5 = 0.25. + * + * The default value depends on the module used. This value doesn't get changed + * when another file is loaded. + * + * @see emotion_object_audio_volume_get() + * + * @ingroup Emotion_Audio + */ +EAPI void emotion_object_audio_volume_set (Evas_Object *obj, double vol); + +/** + * @brief Get the audio volume. + * + * @param obj The object from which we are retrieving the volume. + * @return The current audio volume level for this object. + * + * Get the current value for the audio volume level. Range is from 0.0 to 1.0. + * This volume is set with emotion_object_audio_volume_set(). + * + * @see emotion_object_audio_volume_set() + * + * @ingroup Emotion_Audio + */ +EAPI double emotion_object_audio_volume_get (const Evas_Object *obj); + +/** + * @brief Set the mute audio option for this object. + * + * @param obj The object which we are setting the mute audio option. + * @param mute Whether the audio should be muted (@c EINA_TRUE) or not (@c + * EINA_FALSE). + * + * This function sets the mute audio option for this emotion object. The current + * module used for this object can use this to avoid decoding the audio portion + * of the loaded media file. + * + * @see emotion_object_audio_mute_get() + * @see emotion_object_video_mute_set() + * + * @ingroup Emotion_Audio + */ +EAPI void emotion_object_audio_mute_set (Evas_Object *obj, Eina_Bool mute); + +/** + * @brief Get the mute audio option of this object. + * + * @param obj The object which we are retrieving the mute audio option from. + * @return Whether the audio is muted (@c EINA_TRUE) or not (@c EINA_FALSE). + * + * This function return the mute audio option from this emotion object. It can + * be set with emotion_object_audio_mute_set(). + * + * @see emotion_object_audio_mute_set() + * + * @ingroup Emotion_Audio + */ +EAPI Eina_Bool emotion_object_audio_mute_get (const Evas_Object *obj); +EAPI int emotion_object_audio_channel_count (const Evas_Object *obj); +EAPI const char *emotion_object_audio_channel_name_get(const Evas_Object *obj, int channel); +EAPI void emotion_object_audio_channel_set (Evas_Object *obj, int channel); +EAPI int emotion_object_audio_channel_get (const Evas_Object *obj); + +/** + * @brief Set the mute video option for this object. + * + * @param obj The object which we are setting the mute video option. + * @param mute Whether the video should be muted (@c EINA_TRUE) or not (@c + * EINA_FALSE). + * + * This function sets the mute video option for this emotion object. The + * current module used for this object can use this information to avoid + * decoding the video portion of the loaded media file. + * + * @see emotion_object_video_mute_get() + * @see emotion_object_audio_mute_set() + * + * @ingroup Emotion_Video + */ +EAPI void emotion_object_video_mute_set (Evas_Object *obj, Eina_Bool mute); + +/** + * @brief Get the mute video option of this object. + * + * @param obj The object which we are retrieving the mute video option from. + * @return Whether the video is muted (@c EINA_TRUE) or not (@c EINA_FALSE). + * + * This function returns the mute video option from this emotion object. It can + * be set with emotion_object_video_mute_set(). + * + * @see emotion_object_video_mute_set() + * + * @ingroup Emotion_Video + */ +EAPI Eina_Bool emotion_object_video_mute_get (const Evas_Object *obj); + +/** + * @brief Get the number of available video channel + * + * @param obj The object which we are retrieving the channel count from + * @return the number of available channel. + * + * @see emotion_object_video_channel_name_get() + * + * @ingroup Emotion_Video + */ +EAPI int emotion_object_video_channel_count (const Evas_Object *obj); +EAPI const char *emotion_object_video_channel_name_get(const Evas_Object *obj, int channel); +EAPI void emotion_object_video_channel_set (Evas_Object *obj, int channel); +EAPI int emotion_object_video_channel_get (const Evas_Object *obj); +EAPI void emotion_object_spu_mute_set (Evas_Object *obj, Eina_Bool mute); +EAPI Eina_Bool emotion_object_spu_mute_get (const Evas_Object *obj); +EAPI int emotion_object_spu_channel_count (const Evas_Object *obj); +EAPI const char *emotion_object_spu_channel_name_get (const Evas_Object *obj, int channel); +EAPI void emotion_object_spu_channel_set (Evas_Object *obj, int channel); +EAPI int emotion_object_spu_channel_get (const Evas_Object *obj); +EAPI int emotion_object_chapter_count (const Evas_Object *obj); +EAPI void emotion_object_chapter_set (Evas_Object *obj, int chapter); +EAPI int emotion_object_chapter_get (const Evas_Object *obj); +EAPI const char *emotion_object_chapter_name_get (const Evas_Object *obj, int chapter); +EAPI void emotion_object_eject (Evas_Object *obj); + +/** + * @brief Get the dvd title from this emotion object. + * + * @param obj The object which the title will be retrieved from. + * @return A string containing the title. + * + * This function is only useful when playing a DVD. + * + * @note Don't change or free the string returned by this function. + * + * @ingroup Emotion_Info + */ +EAPI const char *emotion_object_title_get (const Evas_Object *obj); +EAPI const char *emotion_object_ref_file_get (const Evas_Object *obj); +EAPI int emotion_object_ref_num_get (const Evas_Object *obj); +EAPI int emotion_object_spu_button_count_get (const Evas_Object *obj); +EAPI int emotion_object_spu_button_get (const Evas_Object *obj); + +/** + * @brief Retrieve meta information from this file being played. + * + * @param obj The object which the meta info will be extracted from. + * @param meta The type of meta information that will be extracted. + * + * This function retrieves information about the file loaded. It can retrieve + * the track title, artist name, album name, etc. See @ref Emotion_Meta_Info + * for all the possibilities. + * + * The meta info may be not available on all types of files. It will return @c + * NULL if the the file doesn't have meta info, or if this specific field is + * empty. + * + * @note Don't change or free the string returned by this function. + * + * @see Emotion_Meta_Info + * + * @ingroup Emotion_Info + */ +EAPI const char *emotion_object_meta_info_get (const Evas_Object *obj, Emotion_Meta_Info meta); + +/** + * @brief Set the visualization to be used with this object. + * + * @param obj The object where the visualization will be set on. + * @param visualization The type of visualization to be used. + * + * The @p visualization specified will be played instead of a video. This is + * commonly used to display a visualization for audio only files (musics). + * + * The available visualizations are @ref Emotion_Vis. + * + * @see Emotion_Vis + * @see emotion_object_vis_get() + * @see emotion_object_vis_supported() + * + * @ingroup Emotion_Visualization + */ +EAPI void emotion_object_vis_set (Evas_Object *obj, Emotion_Vis visualization); + +/** + * @brief Get the type of visualization in use by this emotion object. + * + * @param obj The emotion object which the visualization is being retrieved + * from. + * @return The type of visualization in use by this object. + * + * The type of visualization can be set by emotion_object_vis_set(). + * + * @see Emotion_Vis + * @see emotion_object_vis_set() + * @see emotion_object_vis_supported() + * + * @ingroup Emotion_Visualization + */ +EAPI Emotion_Vis emotion_object_vis_get (const Evas_Object *obj); + +/** + * @brief Query whether a type of visualization is supported by this object. + * + * @param obj The object which the query is being ran on. + * @param visualization The type of visualization that is being queried. + * @return EINA_TRUE if the visualization is supported, EINA_FALSE otherwise. + * + * This can be used to check if a visualization is supported. e.g.: one wants to + * display a list of available visualizations for a specific object. + * + * @see Emotion_Vis + * @see emotion_object_vis_set() + * @see emotion_object_vis_get() + * + * @ingroup Emotion_Visualization + */ +EAPI Eina_Bool emotion_object_vis_supported (const Evas_Object *obj, Emotion_Vis visualization); + +/** + * @brief Raise priority of an object so it will have a priviledged access to hardware ressource. + * + * @param obj The object which the query is being ran on. + * @param priority EINA_TRUE means give me a priority access to the hardware ressource. + * + * Hardware have a few dedicated hardware pipeline that process the video at no cost for the CPU. + * Especially on SoC, you mostly have one (on mobile phone SoC) or two (on Set Top Box SoC) when + * Picture in Picture is needed. And most application just have a few video stream that really + * deserve high frame rate, hiogh quality output. That's why this call is for. + * + * Please note that if Emotion can't acquire a priviledged hardware ressource, it will fallback + * to the no-priority path. This work on the first asking first get basis system. + * + * @see emotion_object_priority_get() + * + * @ingroup Emotion_Ressource + */ +EAPI void emotion_object_priority_set(Evas_Object *obj, Eina_Bool priority); + +/** + * @brief Get the actual priority of an object. + * + * @param obj The object which the query is being ran on. + * @return EINA_TRUE if the object has a priority access to the hardware. + * + * This actually return the priority status of an object. If it failed to have a priviledged + * access to the hardware, it will return EINA_FALSE. + * + * @see emotion_object_priority_get() + * + * @ingroup Emotion_Ressource + */ +EAPI Eina_Bool emotion_object_priority_get(const Evas_Object *obj); + +/** + * @brief Change the state of an object pipeline. + * + * @param obj The object which the query is being ran on. + * @param state The new state for the object. + * + * Changing the state of a pipeline should help preserve the battery of an embedded device. + * But it will only work sanely if the pipeline is not playing at the time you change its + * state. Depending on the engine all state may be not implemented. + * + * @see Emotion_Suspend + * @see emotion_object_suspend_get() + * + * @ingroup Emotion_Ressource + */ +EAPI void emotion_object_suspend_set(Evas_Object *obj, Emotion_Suspend state); + +/** + * @brief Get the current state of the pipeline + * + * @param obj The object which the query is being ran on. + * @return the current state of the pipeline. + * + * @see Emotion_Suspend + * @see emotion_object_suspend_set() + * + * @ingroup Emotion_Ressource + */ +EAPI Emotion_Suspend emotion_object_suspend_get(Evas_Object *obj); + +/** + * @brief Load the last known position if available + * + * @param obj The object which the query is being ran on. + * + * By using Xattr, Emotion is able, if the system permitt it, to store and retrieve + * the latest position. It should trigger some smart callback to let the application + * know when it succeed or fail. Every operation is fully asynchronous and not + * linked to the actual engine used to play the vide. + * + * @see emotion_object_last_position_save() + * + * @ingroup Emotion_Info + */ +EAPI void emotion_object_last_position_load(Evas_Object *obj); + +/** + * @brief Save the lastest position if possible + * + * @param obj The object which the query is being ran on. + * + * By using Xattr, Emotion is able, if the system permitt it, to store and retrieve + * the latest position. It should trigger some smart callback to let the application + * know when it succeed or fail. Every operation is fully asynchronous and not + * linked to the actual engine used to play the vide. + * + * @see emotion_object_last_position_load() + * + * @ingroup Emotion_Info + */ +EAPI void emotion_object_last_position_save(Evas_Object *obj); + +/** + * @brief Do we have a chance to play that file + * + * @param file A stringshared filename that we want to know if Emotion can play. + * + * This just actually look at the extention of the file, it doesn't check the mime-type + * nor if the file is actually sane. So this is just an hint for your application. + * + * @see emotion_object_extension_may_play_get() + */ +EAPI Eina_Bool emotion_object_extension_may_play_fast_get(const char *file); + +/** + * @brief Do we have a chance to play that file + * + * @param file A filename that we want to know if Emotion can play. + * + * This just actually look at the extention of the file, it doesn't check the mime-type + * nor if the file is actually sane. So this is just an hint for your application. + * + * @see emotion_object_extension_may_play_fast_get() + */ +EAPI Eina_Bool emotion_object_extension_may_play_get(const char *file); + +/** + * @brief Get the actual image object that contains the pixels of the video stream + * + * @param obj The object which the query is being ran on. + * + * This function is usefull when you want to get a direct access to the pixels. + * + * @see emotion_object_image_get() + */ +EAPI Evas_Object *emotion_object_image_get(const Evas_Object *obj); + +/** + * @defgroup Emotion_Webcam API available for accessing webcam + */ + +typedef struct _Emotion_Webcam Emotion_Webcam; /**< Webcam description */ + +EAPI extern int EMOTION_WEBCAM_UPDATE; /**< Ecore_Event triggered when a new webcam is plugged in */ + +/** + * @brief Get a list of active and available webcam + * + * @return the list of available webcam at the time of the call. + * + * It will return the current live list of webcam. It is updated before + * triggering EMOTION_WEBCAM_UPDATE and should never be modified. + * + * @ingroup Emotion_Webcam + */ +EAPI const Eina_List *emotion_webcams_get(void); + +/** + * @brief Get the human understandable name of a Webcam + * + * @param ew The webcam to get the name from. + * @return the actual human readable name. + * + * @ingroup Emotion_Webcam + */ +EAPI const char *emotion_webcam_name_get(const Emotion_Webcam *ew); + +/** + * @brief Get the uri of a Webcam that will be understood by emotion + * + * @param ew The webcam to get the uri from. + * @return the actual uri that emotion will later understood. + * + * @ingroup Emotion_Webcam + */ +EAPI const char *emotion_webcam_device_get(const Emotion_Webcam *ew); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am new file mode 100644 index 0000000..a2d2198 --- /dev/null +++ b/src/lib/Makefile.am @@ -0,0 +1,59 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EMOTION_CPPFLAGS@ \ +@EMOTION_CFLAGS@ \ +@EIO_CFLAGS@ \ +@EFL_EMOTION_BUILD@ \ +@EEZE_CFLAGS@ + +if EMOTION_STATIC_BUILD_XINE +AM_CPPFLAGS += @XINE_CFLAGS@ +endif + +if EMOTION_STATIC_BUILD_GSTREAMER +AM_CPPFLAGS += @GSTREAMER_CFLAGS@ +endif + +lib_LTLIBRARIES = libemotion.la +includes_HEADERS = Emotion.h +includesdir = $(includedir)/emotion-@VMAJ@ + +libemotion_la_SOURCES = emotion_smart.c emotion_main.c + +if EMOTION_STATIC_BUILD_XINE +libemotion_la_SOURCES += \ +$(top_srcdir)/src/modules/xine/emotion_xine.c \ +$(top_srcdir)/src/modules/xine/emotion_xine_vo_out.c +endif + +if EMOTION_STATIC_BUILD_GSTREAMER +libemotion_la_SOURCES += \ +$(top_srcdir)/src/modules/gstreamer/emotion_gstreamer.c \ +$(top_srcdir)/src/modules/gstreamer/emotion_sink.c +endif + +if EMOTION_STATIC_BUILD_GENERIC +libemotion_la_SOURCES += \ +$(top_srcdir)/src/modules/generic/emotion_generic.c +endif + +libemotion_la_LIBADD = @EMOTION_LIBS@ @EIO_LIBS@ @EEZE_LIBS@ + +if EMOTION_STATIC_BUILD_XINE +libemotion_la_LIBADD += @XINE_LIBS@ +endif + +if EMOTION_STATIC_BUILD_GSTREAMER +libemotion_la_LIBADD += @GSTREAMER_LIBS@ +endif + +libemotion_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ + +EXTRA_DIST = emotion_private.h diff --git a/src/lib/emotion_main.c b/src/lib/emotion_main.c new file mode 100644 index 0000000..52b1baa --- /dev/null +++ b/src/lib/emotion_main.c @@ -0,0 +1,484 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include +# define alloca _alloca +# elif !defined HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#include + +#ifdef EMOTION_HAVE_EEZE +# include +# include +# include +# include +# ifdef HAVE_V4L2 +# include +# endif + +# include +# include +#endif + +#include + +#include "Emotion.h" +#include "emotion_private.h" + +static Emotion_Version _version = { VMAJ, VMIN, VMIC, VREV }; +static int emotion_pending_objects = 0; +EAPI Emotion_Version *emotion_version = &_version; + +EAPI int EMOTION_WEBCAM_UPDATE = 0; + +struct ext_match_s +{ + unsigned int length; + const char *extension; +}; + +#define MATCHING(Ext) \ + { sizeof (Ext), Ext } + +static const struct ext_match_s matchs[] = +{ /* map extensions to know if it's a emotion playable content for good first-guess tries */ + MATCHING(".264"), + MATCHING(".3g2"), + MATCHING(".3gp"), + MATCHING(".3gp2"), + MATCHING(".3gpp"), + MATCHING(".3gpp2"), + MATCHING(".3p2"), + MATCHING(".asf"), + MATCHING(".avi"), + MATCHING(".bdm"), + MATCHING(".bdmv"), + MATCHING(".clpi"), + MATCHING(".clp"), + MATCHING(".fla"), + MATCHING(".flv"), + MATCHING(".m1v"), + MATCHING(".m2v"), + MATCHING(".m2t"), + MATCHING(".m4v"), + MATCHING(".mkv"), + MATCHING(".mov"), + MATCHING(".mp2"), + MATCHING(".mp2ts"), + MATCHING(".mp4"), + MATCHING(".mpe"), + MATCHING(".mpeg"), + MATCHING(".mpg"), + MATCHING(".mpl"), + MATCHING(".mpls"), + MATCHING(".mts"), + MATCHING(".mxf"), + MATCHING(".nut"), + MATCHING(".nuv"), + MATCHING(".ogg"), + MATCHING(".ogm"), + MATCHING(".ogv"), + MATCHING(".rm"), + MATCHING(".rmj"), + MATCHING(".rmm"), + MATCHING(".rms"), + MATCHING(".rmx"), + MATCHING(".rmvb"), + MATCHING(".swf"), + MATCHING(".ts"), + MATCHING(".weba"), + MATCHING(".webm"), + MATCHING(".wmv") +}; + +Eina_Bool +_emotion_object_extension_can_play_generic_get(const void *data __UNUSED__, const char *file) +{ + unsigned int length; + unsigned int i; + + length = eina_stringshare_strlen(file) + 1; + if (length < 5) return EINA_FALSE; + + for (i = 0; i < sizeof (matchs) / sizeof (struct ext_match_s); ++i) + { + if (matchs[i].length > length) continue; + + if (!strcasecmp(matchs[i].extension, + file + length - matchs[i].length)) + return EINA_TRUE; + } + + return EINA_FALSE; +} + +EAPI Eina_Bool +emotion_object_extension_may_play_fast_get(const char *file) +{ + if (!file) return EINA_FALSE; + return _emotion_object_extension_can_play_generic_get(NULL, file); +} + +EAPI Eina_Bool +emotion_object_extension_may_play_get(const char *file) +{ + const char *tmp; + Eina_Bool result; + + if (!file) return EINA_FALSE; + tmp = eina_stringshare_add(file); + result = emotion_object_extension_may_play_fast_get(tmp); + eina_stringshare_del(tmp); + + return result; +} + +typedef struct _Emotion_Webcams Emotion_Webcams; + +struct _Emotion_Webcams +{ + Eina_List *webcams; +}; + +struct _Emotion_Webcam +{ + EINA_REFCOUNT; + + const char *syspath; + const char *device; + const char *name; + + const char *custom; + + const char *filename; +}; + +static int _emotion_webcams_count = 0; +static Eet_Data_Descriptor *_webcam_edd; +static Eet_Data_Descriptor *_webcams_edd; + +static Emotion_Webcams *_emotion_webcams = NULL; +static Eet_File *_emotion_webcams_file = NULL; + +static Eet_Data_Descriptor * +_emotion_webcams_data(void) +{ + Eet_Data_Descriptor_Class eddc; + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcam); + _webcam_edd = eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "device", device, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "name", name, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "custom", custom, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "filename", filename, EET_T_STRING); + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcams); + _webcams_edd = eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_LIST(_webcams_edd, Emotion_Webcams, "webcams", webcams, _webcam_edd); + + return _webcams_edd; +} + +#ifdef EMOTION_HAVE_EEZE +static Eeze_Udev_Watch *eeze_watcher = NULL; + +static void +emotion_webcam_destroy(Emotion_Webcam *ew) +{ + if (!ew->custom) + { + eina_stringshare_del(ew->syspath); + eina_stringshare_del(ew->device); + eina_stringshare_del(ew->name); + } + free(ew); +} + +static void +_emotion_check_device(Emotion_Webcam *ew) +{ +#ifdef HAVE_V4L2 + Emotion_Webcam *check; + Eina_List *l; + struct v4l2_capability caps; + int fd; +#endif + + if (!ew) return ; +#ifdef HAVE_V4L2 + if (!ew->device) goto on_error; + + fd = open(ew->filename, O_RDONLY); + if (fd < 0) goto on_error; + + if (ioctl(fd, VIDIOC_QUERYCAP, &caps) == -1) goto on_error; + + /* Likely not a webcam */ + if (!caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) goto on_error; + if (caps.capabilities & V4L2_CAP_TUNER + || caps.capabilities & V4L2_CAP_RADIO + || caps.capabilities & V4L2_CAP_MODULATOR) + goto on_error; + + EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check) + if (check->device == ew->device) + goto on_error; + + _emotion_webcams->webcams = eina_list_append(_emotion_webcams->webcams, ew); + + EINA_REFCOUNT_INIT(ew); + + return ; + + on_error: +#endif + fprintf(stderr, "'%s' is not a webcam ['%s']\n", ew->name, strerror(errno)); + eina_stringshare_del(ew->syspath); + eina_stringshare_del(ew->device); + eina_stringshare_del(ew->name); + free(ew); +} + +static Emotion_Webcam * +_emotion_webcam_new(const char *syspath) +{ + Emotion_Webcam *test; + const char *device; + char *local; + + test = malloc(sizeof (Emotion_Webcam)); + if (!test) return NULL; + + test->custom = NULL; + test->syspath = eina_stringshare_ref(syspath); + test->name = eeze_udev_syspath_get_sysattr(syspath, "name"); + + device = eeze_udev_syspath_get_property(syspath, "DEVNAME"); + local = alloca(eina_stringshare_strlen(device) + 8); + snprintf(local, eina_stringshare_strlen(device) + 8, "v4l2://%s", device); + test->device = eina_stringshare_add(local); + eina_stringshare_del(device); + test->filename = test->device + 7; + + return test; +} + +static void +_emotion_enumerate_all_webcams(void) +{ + Eina_List *devices; + const char *syspath; + + devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_V4L, NULL); + + EINA_LIST_FREE(devices, syspath) + { + Emotion_Webcam *test; + + test = _emotion_webcam_new(syspath); + if (test) _emotion_check_device(test); + + eina_stringshare_del(syspath); + } +} + +static void +_emotion_eeze_events(const char *syspath, + Eeze_Udev_Event ev, + void *data __UNUSED__, + Eeze_Udev_Watch *watcher __UNUSED__) +{ + if (ev == EEZE_UDEV_EVENT_REMOVE) + { + Emotion_Webcam *check; + Eina_List *l; + + EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check) + if (check->syspath == syspath) + { + _emotion_webcams->webcams = eina_list_remove_list(_emotion_webcams->webcams, l); + EINA_REFCOUNT_UNREF(check) + emotion_webcam_destroy(check); + break ; + } + } + else if (ev == EEZE_UDEV_EVENT_ADD) + { + Emotion_Webcam *test; + + test = _emotion_webcam_new(syspath); + if (test) _emotion_check_device(test); + } + ecore_event_add(EMOTION_WEBCAM_UPDATE, NULL, NULL, NULL); +} + +#endif + +EAPI Eina_Bool +emotion_init(void) +{ + char buffer[4096]; + + if (_emotion_webcams_count++) return EINA_TRUE; + + ecore_init(); + + snprintf(buffer, 4096, "%s/emotion.cfg", PACKAGE_DATA_DIR); + _emotion_webcams_file = eet_open(buffer, EET_FILE_MODE_READ); + if (_emotion_webcams_file) + { + Eet_Data_Descriptor *edd; + + edd = _emotion_webcams_data(); + + _emotion_webcams = eet_data_read(_emotion_webcams_file, edd, "config"); + + eet_data_descriptor_free(_webcams_edd); _webcams_edd = NULL; + eet_data_descriptor_free(_webcam_edd); _webcam_edd = NULL; + } + + if (!_emotion_webcams) + { + _emotion_webcams = calloc(1, sizeof (Emotion_Webcams)); + if (!_emotion_webcams) return EINA_FALSE; + } + +#ifdef EMOTION_HAVE_EEZE + EMOTION_WEBCAM_UPDATE = ecore_event_type_new(); + + eeze_init(); + + _emotion_enumerate_all_webcams(); + + eeze_watcher = eeze_udev_watch_add(EEZE_UDEV_TYPE_V4L, + (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE), + _emotion_eeze_events, NULL); +#endif + + return EINA_TRUE; +} + +EAPI Eina_Bool +emotion_shutdown(void) +{ + Emotion_Webcam *ew; + double start; + + if (_emotion_webcams_count <= 0) + { + EINA_LOG_ERR("Init count not greater than 0 in shutdown."); + return EINA_FALSE; + } + if (--_emotion_webcams_count) return EINA_TRUE; + + EINA_LIST_FREE(_emotion_webcams->webcams, ew) + { +#ifdef EMOTION_HAVE_EEZE + /* There is currently no way to refcount from the outside, this help, but could lead to some issue */ + EINA_REFCOUNT_UNREF(ew) + emotion_webcam_destroy(ew); +#endif + } + free(_emotion_webcams); + _emotion_webcams = NULL; + + if (_emotion_webcams_file) + { + /* As long as there is no one reference any pointer, you are safe */ + eet_close(_emotion_webcams_file); + _emotion_webcams_file = NULL; + } + +#ifdef EMOTION_HAVE_EEZE + eeze_udev_watch_del(eeze_watcher); + eeze_watcher = NULL; + + eeze_shutdown(); +#endif + + start = ecore_time_get(); + while (emotion_pending_objects && ecore_time_get() - start < 0.5) + ecore_main_loop_iterate(); + + if (emotion_pending_objects) + { + EINA_LOG_ERR("There is still %i Emotion pipeline running", emotion_pending_objects); + } + + ecore_shutdown(); + + return EINA_TRUE; +} + +EAPI const Eina_List * +emotion_webcams_get(void) +{ + return _emotion_webcams->webcams; +} + +EAPI const char * +emotion_webcam_name_get(const Emotion_Webcam *ew) +{ + if (!ew) return NULL; + + return ew->name; +} + +EAPI const char * +emotion_webcam_device_get(const Emotion_Webcam *ew) +{ + if (!ew) return NULL; + + return ew->device; +} + +EAPI const char * +emotion_webcam_custom_get(const char *device) +{ + const Emotion_Webcam *ew; + const Eina_List *l; + + if (_emotion_webcams) + { + EINA_LIST_FOREACH(_emotion_webcams->webcams, l, ew) + if (ew->device && strcmp(device, ew->device) == 0) + return ew->custom; + } + + return NULL; +} + +EAPI void +_emotion_pending_object_ref(void) +{ + emotion_pending_objects++; +} + +EAPI void +_emotion_pending_object_unref(void) +{ + emotion_pending_objects--; +} diff --git a/src/lib/emotion_private.h b/src/lib/emotion_private.h new file mode 100644 index 0000000..cf24c75 --- /dev/null +++ b/src/lib/emotion_private.h @@ -0,0 +1,135 @@ +#ifndef EMOTION_PRIVATE_H +#define EMOTION_PRIVATE_H + +#define META_TRACK_TITLE 1 +#define META_TRACK_ARTIST 2 +#define META_TRACK_GENRE 3 +#define META_TRACK_COMMENT 4 +#define META_TRACK_ALBUM 5 +#define META_TRACK_YEAR 6 +#define META_TRACK_DISCID 7 +#define META_TRACK_COUNT 8 + +typedef enum _Emotion_Format Emotion_Format; +typedef struct _Emotion_Video_Module Emotion_Video_Module; +typedef struct _Emotion_Module_Options Emotion_Module_Options; +typedef struct _Eina_Emotion_Plugins Eina_Emotion_Plugins; + +typedef Eina_Bool (*Emotion_Module_Open)(Evas_Object *, const Emotion_Video_Module **, void **, Emotion_Module_Options *); +typedef void (*Emotion_Module_Close)(Emotion_Video_Module *module, void *); + +enum _Emotion_Format +{ + EMOTION_FORMAT_NONE, + EMOTION_FORMAT_I420, + EMOTION_FORMAT_YV12, + EMOTION_FORMAT_YUY2, /* unused for now since evas does not support yuy2 format */ + EMOTION_FORMAT_BGRA +}; + +struct _Emotion_Module_Options +{ + const char *player; + Eina_Bool no_video : 1; + Eina_Bool no_audio : 1; +}; + +struct _Eina_Emotion_Plugins +{ + Emotion_Module_Open open; + Emotion_Module_Close close; +}; + +struct _Emotion_Video_Module +{ + unsigned char (*init) (Evas_Object *obj, void **video, Emotion_Module_Options *opt); + int (*shutdown) (void *video); + unsigned char (*file_open) (const char *file, Evas_Object *obj, void *video); + void (*file_close) (void *ef); + void (*play) (void *ef, double pos); + void (*stop) (void *ef); + void (*size_get) (void *ef, int *w, int *h); + void (*pos_set) (void *ef, double pos); + double (*len_get) (void *ef); + double (*buffer_size_get) (void *ef); + int (*fps_num_get) (void *ef); + int (*fps_den_get) (void *ef); + double (*fps_get) (void *ef); + double (*pos_get) (void *ef); + void (*vis_set) (void *ef, Emotion_Vis vis); + Emotion_Vis (*vis_get) (void *ef); + Eina_Bool (*vis_supported) (void *ef, Emotion_Vis vis); + double (*ratio_get) (void *ef); + int (*video_handled) (void *ef); + int (*audio_handled) (void *ef); + int (*seekable) (void *ef); + void (*frame_done) (void *ef); + Emotion_Format (*format_get) (void *ef); + void (*video_data_size_get) (void *ef, int *w, int *h); + int (*yuv_rows_get) (void *ef, int w, int h, unsigned char **yrows, unsigned char **urows, unsigned char **vrows); + int (*bgra_data_get) (void *ef, unsigned char **bgra_data); + void (*event_feed) (void *ef, int event); + void (*event_mouse_button_feed) (void *ef, int button, int x, int y); + void (*event_mouse_move_feed) (void *ef, int x, int y); + int (*video_channel_count) (void *ef); + void (*video_channel_set) (void *ef, int channel); + int (*video_channel_get) (void *ef); + const char * (*video_channel_name_get) (void *ef, int channel); + void (*video_channel_mute_set) (void *ef, int mute); + int (*video_channel_mute_get) (void *ef); + int (*audio_channel_count) (void *ef); + void (*audio_channel_set) (void *ef, int channel); + int (*audio_channel_get) (void *ef); + const char * (*audio_channel_name_get) (void *ef, int channel); + void (*audio_channel_mute_set) (void *ef, int mute); + int (*audio_channel_mute_get) (void *ef); + void (*audio_channel_volume_set) (void *ef, double vol); + double (*audio_channel_volume_get) (void *ef); + int (*spu_channel_count) (void *ef); + void (*spu_channel_set) (void *ef, int channel); + int (*spu_channel_get) (void *ef); + const char * (*spu_channel_name_get) (void *ef, int channel); + void (*spu_channel_mute_set) (void *ef, int mute); + int (*spu_channel_mute_get) (void *ef); + int (*chapter_count) (void *ef); + void (*chapter_set) (void *ef, int chapter); + int (*chapter_get) (void *ef); + const char * (*chapter_name_get) (void *ef, int chapter); + void (*speed_set) (void *ef, double speed); + double (*speed_get) (void *ef); + int (*eject) (void *ef); + const char * (*meta_get) (void *ef, int meta); + void (*priority_set) (void *ef, Eina_Bool priority); + Eina_Bool (*priority_get) (void *ef); + + Eina_Emotion_Plugins *plugin; +}; + +EAPI void *_emotion_video_get(const Evas_Object *obj); +EAPI void _emotion_frame_new(Evas_Object *obj); +EAPI void _emotion_video_pos_update(Evas_Object *obj, double pos, double len); +EAPI void _emotion_frame_resize(Evas_Object *obj, int w, int h, double ratio); +EAPI void _emotion_frame_refill(Evas_Object *obj, double w, double h); +EAPI void _emotion_decode_stop(Evas_Object *obj); +EAPI void _emotion_open_done(Evas_Object *obj); +EAPI void _emotion_playback_started(Evas_Object *obj); +EAPI void _emotion_playback_finished(Evas_Object *obj); +EAPI void _emotion_audio_level_change(Evas_Object *obj); +EAPI void _emotion_channels_change(Evas_Object *obj); +EAPI void _emotion_title_set(Evas_Object *obj, char *title); +EAPI void _emotion_progress_set(Evas_Object *obj, char *info, double stat); +EAPI void _emotion_file_ref_set(Evas_Object *obj, const char *file, int num); +EAPI void _emotion_spu_button_num_set(Evas_Object *obj, int num); +EAPI void _emotion_spu_button_set(Evas_Object *obj, int button); +EAPI void _emotion_seek_done(Evas_Object *obj); +EAPI void _emotion_image_reset(Evas_Object *obj); + +EAPI Eina_Bool _emotion_module_register(const char *name, Emotion_Module_Open open, Emotion_Module_Close close); +EAPI Eina_Bool _emotion_module_unregister(const char *name); + +EAPI const char *emotion_webcam_custom_get(const char *device); + +EAPI void _emotion_pending_object_ref(void); +EAPI void _emotion_pending_object_unref(void); + +#endif diff --git a/src/lib/emotion_smart.c b/src/lib/emotion_smart.c new file mode 100644 index 0000000..48eafda --- /dev/null +++ b/src/lib/emotion_smart.c @@ -0,0 +1,2110 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#ifdef HAVE_EIO +# include +# include +#endif + +#include "Emotion.h" +#include "emotion_private.h" + +#ifdef _WIN32 +# define FMT_UCHAR "%c" +#else +# define FMT_UCHAR "%hhu" +#endif + +#define E_SMART_OBJ_GET(smart, o, type) \ + { \ + char *_e_smart_str; \ + \ + if (!o) return; \ + smart = evas_object_smart_data_get(o); \ + if (!smart) return; \ + _e_smart_str = (char *)evas_object_type_get(o); \ + if (!_e_smart_str) return; \ + if (strcmp(_e_smart_str, type)) return; \ + } + +#define E_SMART_OBJ_GET_RETURN(smart, o, type, ret) \ + { \ + char *_e_smart_str; \ + \ + if (!o) return ret; \ + smart = evas_object_smart_data_get(o); \ + if (!smart) return ret; \ + _e_smart_str = (char *)evas_object_type_get(o); \ + if (!_e_smart_str) return ret; \ + if (strcmp(_e_smart_str, type)) return ret; \ + } + +#define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(_log_domain, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(_log_domain, __VA_ARGS__) +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_domain, __VA_ARGS__) + +#define E_OBJ_NAME "emotion_object" + +typedef struct _Smart_Data Smart_Data; + +struct _Smart_Data +{ + EINA_REFCOUNT; + Emotion_Video_Module *module; + void *video_data; + + char *module_name; + + const char *file; + Evas_Object *obj; + Evas_Object *bg; + + Ecore_Job *job; + + char *title; + +#ifdef HAVE_EIO + Eio_File *load_xattr; + Eio_File *save_xattr; +#endif + + struct { + char *info; + double stat; + } progress; + struct { + char *file; + int num; + } ref; + struct { + int button_num; + int button; + } spu; + struct { + int l; /* left */ + int r; /* right */ + int t; /* top */ + int b; /* bottom */ + Evas_Object *clipper; + } crop; + + struct { + int w, h; + } video; + struct { + double w, h; + } fill; + + double ratio; + double pos; + double remember_jump; + double seek_pos; + double len; + + Emotion_Module_Options module_options; + + Emotion_Suspend state; + Emotion_Aspect aspect; + + Ecore_Animator *anim; + + Eina_Bool open : 1; + Eina_Bool play : 1; + Eina_Bool remember_play : 1; + Eina_Bool seek : 1; + Eina_Bool seeking : 1; +}; + +static void _mouse_move(void *data, Evas *ev, Evas_Object *obj, void *event_info); +static void _mouse_down(void *data, Evas *ev, Evas_Object *obj, void *event_info); +static void _pos_set_job(void *data); +static void _pixels_get(void *data, Evas_Object *obj); + +static void _smart_init(void); +static void _smart_add(Evas_Object * obj); +static void _smart_del(Evas_Object * obj); +static void _smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y); +static void _smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h); +static void _smart_show(Evas_Object * obj); +static void _smart_hide(Evas_Object * obj); +static void _smart_color_set(Evas_Object * obj, int r, int g, int b, int a); +static void _smart_clip_set(Evas_Object * obj, Evas_Object * clip); +static void _smart_clip_unset(Evas_Object * obj); + +/**********************************/ +/* Globals for the E Video Object */ +/**********************************/ +static Evas_Smart *smart = NULL; +static Eina_Hash *_backends = NULL; +static Eina_Array *_modules = NULL; +static int _log_domain = -1; + +static const char *_backend_priority[] = { + "gstreamer", + "xine", + "generic" +}; + +static const char SIG_FRAME_DECODE[] = "frame_decode"; +static const char SIG_POSITION_UPDATE[] = "position_update"; +static const char SIG_LENGTH_CHANGE[] = "length_change"; +static const char SIG_FRAME_RESIZE[] = "frame_resize"; +static const char SIG_DECODE_STOP[] = "decode_stop"; +static const char SIG_PLAYBACK_STARTED[] = "playback_started"; +static const char SIG_PLAYBACK_FINISHED[] = "playback_finished"; +static const char SIG_AUDIO_LEVEL_CHANGE[] = "audio_level_change"; +static const char SIG_CHANNELS_CHANGE[] = "channels_change"; +static const char SIG_TITLE_CHANGE[] = "title_change"; +static const char SIG_PROGRESS_CHANGE[] = "progress_change"; +static const char SIG_REF_CHANGE[] = "ref_change"; +static const char SIG_BUTTON_NUM_CHANGE[] = "button_num_change"; +static const char SIG_BUTTON_CHANGE[] = "button_change"; +static const char SIG_OPEN_DONE[] = "open_done"; +static const char SIG_POSITION_SAVE_SUCCEED[] = "position_save,succeed"; +static const char SIG_POSITION_SAVE_FAILED[] = "position_save,failed"; +static const char SIG_POSITION_LOAD_SUCCEED[] = "position_load,succeed"; +static const char SIG_POSITION_LOAD_FAILED[] = "position_load,failed"; + +static const Evas_Smart_Cb_Description _smart_callbacks[] = { + {SIG_FRAME_DECODE, ""}, + {SIG_POSITION_UPDATE, ""}, + {SIG_LENGTH_CHANGE, ""}, + {SIG_FRAME_RESIZE, ""}, + {SIG_DECODE_STOP, ""}, + {SIG_PLAYBACK_STARTED, ""}, + {SIG_PLAYBACK_FINISHED, ""}, + {SIG_AUDIO_LEVEL_CHANGE, ""}, + {SIG_CHANNELS_CHANGE, ""}, + {SIG_TITLE_CHANGE, ""}, + {SIG_PROGRESS_CHANGE, ""}, + {SIG_REF_CHANGE, ""}, + {SIG_BUTTON_NUM_CHANGE, ""}, + {SIG_BUTTON_CHANGE, ""}, + {SIG_OPEN_DONE, ""}, + {NULL, NULL} +}; + +static void +_emotion_image_data_zero(Evas_Object *img) +{ + void *data; + + data = evas_object_image_data_get(img, 1); + if (data) + { + int w, h, sz = 0; + Evas_Colorspace cs; + + evas_object_image_size_get(img, &w, &h); + cs = evas_object_image_colorspace_get(img); + if (cs == EVAS_COLORSPACE_ARGB8888) + sz = w * h * 4; + if ((cs == EVAS_COLORSPACE_YCBCR422P601_PL) || + (cs == EVAS_COLORSPACE_YCBCR422P709_PL)) + sz = h * 2 * sizeof(unsigned char *); + if (sz != 0) memset(data, 0, sz); + } + evas_object_image_data_set(img, data); +} + +static void +_emotion_module_close(Emotion_Video_Module *mod, void *video) +{ + if (!mod) return; + if (mod->plugin->close && video) + mod->plugin->close(mod, video); + /* FIXME: we can't go dlclosing here as a thread still may be running from + * the module - this in theory will leak- but it shouldn't be too bad and + * mean that once a module is dlopened() it can't be closed - its refcount + * will just keep going up + */ +} + +static void +_smart_data_free(Smart_Data *sd) +{ + if (sd->video_data) sd->module->file_close(sd->video_data); + _emotion_module_close(sd->module, sd->video_data); + evas_object_del(sd->obj); + evas_object_del(sd->crop.clipper); + evas_object_del(sd->bg); + eina_stringshare_del(sd->file); + free(sd->module_name); + if (sd->job) ecore_job_del(sd->job); + if (sd->anim) ecore_animator_del(sd->anim); + free(sd->progress.info); + free(sd->ref.file); + free(sd); + + ecore_shutdown(); +} + +EAPI Eina_Bool +_emotion_module_register(const char *name, Emotion_Module_Open mod_open, Emotion_Module_Close mod_close) +{ + Eina_Emotion_Plugins *plugin; + + plugin = malloc(sizeof (Eina_Emotion_Plugins)); + if (!plugin) return EINA_FALSE; + + plugin->open = mod_open; + plugin->close = mod_close; + + return eina_hash_add(_backends, name, plugin); +} + +EAPI Eina_Bool +_emotion_module_unregister(const char *name) +{ + return eina_hash_del(_backends, name, NULL); +} + +static const char * +_emotion_module_open(const char *name, Evas_Object *obj, Emotion_Video_Module **mod, void **video) +{ + Eina_Emotion_Plugins *plugin; + Smart_Data *sd; + unsigned int i = 0; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!_backends) + { + ERR("No backend loaded"); + return NULL; + } + + if (!name && getenv("EMOTION_ENGINE")) + name = getenv("EMOTION_ENGINE"); + + /* FIXME: Always look for a working backend. */ + retry: + if (!name || i > 0) + name = _backend_priority[i++]; + + plugin = eina_hash_find(_backends, name); + if (!plugin) + { + if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*))) + goto retry; + + ERR("No backend loaded"); + return EINA_FALSE; + } + + if (plugin->open(obj, (const Emotion_Video_Module **) mod, video, &(sd->module_options))) + { + if (*mod) + { + (*mod)->plugin = plugin; + return name; + } + } + + if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*))) + goto retry; + + ERR("Unable to load module: %s", name); + + return NULL; +} + +static void +_clipper_position_size_update(Evas_Object *obj, int x, int y, int w, int h, int vid_w, int vid_h) +{ + Smart_Data *sd; + double scale_w, scale_h; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + + if (vid_w == 0 || vid_h == 0) + { + evas_object_image_fill_set(sd->obj, 0, 0, 0, 0); + evas_object_move(sd->obj, x, y); + evas_object_resize(sd->obj, 0, 0); + evas_object_move(sd->crop.clipper, x, y); + evas_object_resize(sd->crop.clipper, 0, 0); + } + else + { + evas_object_move(sd->crop.clipper, x, y); + scale_w = (double)w / (double)(vid_w - sd->crop.l - sd->crop.r); + scale_h = (double)h / (double)(vid_h - sd->crop.t - sd->crop.b); + + if (sd->fill.w < 0 && sd->fill.h < 0) + evas_object_image_fill_set(sd->obj, 0, 0, vid_w * scale_w, vid_h * scale_h); + else + evas_object_image_fill_set(sd->obj, 0, 0, sd->fill.w * w, sd->fill.h * h); + evas_object_resize(sd->obj, vid_w * scale_w, vid_h * scale_h); + evas_object_move(sd->obj, x - sd->crop.l * scale_w, y - sd->crop.t * scale_h); + evas_object_resize(sd->crop.clipper, w, h); + } +} + +/*******************************/ +/* Externally accessible calls */ +/*******************************/ + + + +EAPI Evas_Object * +emotion_object_add(Evas *evas) +{ + _smart_init(); + return evas_object_smart_add(evas, smart); +} + +EAPI Evas_Object * +emotion_object_image_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + sd = evas_object_smart_data_get(obj); + if (!sd) return NULL; + return sd->obj; +} + +EAPI void +emotion_object_module_option_set(Evas_Object *obj, const char *opt, const char *val) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if ((!opt) || (!val)) return; + + if (!strcmp(opt, "player")) + eina_stringshare_replace(&sd->module_options.player, val); +} + +EAPI Eina_Bool +emotion_object_init(Evas_Object *obj, const char *module_filename) +{ + Smart_Data *sd; + const char *file; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + + if ((sd->module_name) && module_filename && (!strcmp(sd->module_name, module_filename))) + return EINA_TRUE; + free(sd->module_name); + sd->module_name = NULL; + + file = sd->file; + sd->file = NULL; + + free(sd->title); + sd->title = NULL; + free(sd->progress.info); + sd->progress.info = NULL; + sd->progress.stat = 0.0; + free(sd->ref.file); + sd->ref.file = NULL; + sd->ref.num = 0; + sd->spu.button_num = 0; + sd->spu.button = -1; + sd->ratio = 1.0; + sd->pos = 0; + sd->remember_jump = 0; + sd->seek_pos = 0; + sd->len = 0; + sd->remember_play = 0; + + if (sd->anim) ecore_animator_del(sd->anim); + sd->anim = NULL; + + _emotion_module_close(sd->module, sd->video_data); + sd->module = NULL; + sd->video_data = NULL; + + module_filename = _emotion_module_open(module_filename, obj, &sd->module, &sd->video_data); + if (!module_filename) + return EINA_FALSE; + + sd->module_name = strdup(module_filename); + + if (file) + { + emotion_object_file_set(obj, file); + eina_stringshare_del(file); + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +emotion_object_file_set(Evas_Object *obj, const char *file) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EINA_FALSE); + + DBG("file=%s", file); + if (!sd->module) return EINA_FALSE; + + sd->video.w = 0; + sd->video.h = 0; + if ((file) && (sd->file) && + ((file == sd->file) || (!strcmp(file, sd->file)))) return EINA_FALSE; + if ((file) && (file[0] != 0)) + { + eina_stringshare_replace(&sd->file, file); + sd->module->file_close(sd->video_data); + evas_object_image_data_set(sd->obj, NULL); + evas_object_image_size_set(sd->obj, 1, 1); + _emotion_image_data_zero(sd->obj); + sd->open = 0; + if (!sd->module->file_open(sd->file, obj, sd->video_data)) + return EINA_FALSE; + sd->pos = 0.0; + if (sd->play) sd->module->play(sd->video_data, 0.0); + } + else + { + if (sd->video_data && sd->module) + { + sd->module->file_close(sd->video_data); + evas_object_image_data_set(sd->obj, NULL); + evas_object_image_size_set(sd->obj, 1, 1); + _emotion_image_data_zero(sd->obj); + } + eina_stringshare_replace(&sd->file, NULL); + } + + if (sd->anim) ecore_animator_del(sd->anim); + sd->anim = NULL; + +#ifdef HAVE_EIO + /* Only cancel the load_xattr or we will loose ref to time_seek stringshare */ + if (sd->load_xattr) eio_file_cancel(sd->load_xattr); + sd->load_xattr = NULL; + if (sd->save_xattr) eio_file_cancel(sd->save_xattr); + sd->save_xattr = NULL; +#endif + + return EINA_TRUE; +} + +EAPI const char * +emotion_object_file_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + return sd->file; +} + +static void +_emotion_aspect_borders_apply(Evas_Object *obj, Smart_Data *sd, int w, int h, int iw, int ih) +{ + int x, y; + + evas_object_geometry_get(obj, &x, &y, NULL, NULL); + + /* applying calculated borders */ + if (sd->crop.l == 0 && sd->crop.r == 0 && + sd->crop.t == 0 && sd->crop.b == 0) + { + Evas_Object *old_clipper; + if (sd->crop.clipper) + { + old_clipper = evas_object_clip_get(sd->crop.clipper); + evas_object_clip_unset(sd->obj); + evas_object_clip_set(sd->obj, old_clipper); + evas_object_del(sd->crop.clipper); + sd->crop.clipper = NULL; + } + } + else + { + if (!sd->crop.clipper) + { + Evas_Object *old_clipper; + sd->crop.clipper = evas_object_rectangle_add( + evas_object_evas_get(obj)); + evas_object_color_set(sd->crop.clipper, 255, 255, 255, 255); + evas_object_smart_member_add(sd->crop.clipper, obj); + old_clipper = evas_object_clip_get(sd->obj); + evas_object_clip_set(sd->obj, sd->crop.clipper); + evas_object_clip_set(sd->crop.clipper, old_clipper); + if (evas_object_visible_get(sd->obj)) + evas_object_show(sd->crop.clipper); + } + } + _clipper_position_size_update(obj, x, y, w, h, iw, ih); +} + +static void +_emotion_object_aspect_border_apply(Evas_Object *obj, Smart_Data *sd, int w, int h) +{ + int iw, ih; + double ir; + double r; + + int aspect_opt = 0; + + iw = sd->video.w; + ih = sd->video.h; + + ir = (double)iw / ih; + r = (double)w / h; + + /* First check if we should fit the width or height of the video inside the + * width/height of the object. This check takes into account the original + * aspect ratio and the object aspect ratio, if we are keeping both sizes or + * cropping the exceding area. + */ + if (sd->aspect == EMOTION_ASPECT_KEEP_NONE) + { + sd->crop.l = 0; + sd->crop.r = 0; + sd->crop.t = 0; + sd->crop.b = 0; + aspect_opt = 0; // just ignore keep_aspect + } + else if (sd->aspect == EMOTION_ASPECT_KEEP_WIDTH) + { + aspect_opt = 1; + } + else if (sd->aspect == EMOTION_ASPECT_KEEP_HEIGHT) + { + aspect_opt = 2; + } + else if (sd->aspect == EMOTION_ASPECT_KEEP_BOTH) + { + if (ir > r) + aspect_opt = 1; + else + aspect_opt = 2; + } + else if (sd->aspect == EMOTION_ASPECT_CROP) + { + if (ir > r) + aspect_opt = 2; + else + aspect_opt = 1; + } + else if (sd->aspect == EMOTION_ASPECT_CUSTOM) + { + // nothing to do, just respect the border settings + aspect_opt = 0; + } + + /* updating borders based on keep_aspect settings */ + if (aspect_opt == 1) // keep width + { + int th, dh; + double scale; + + sd->crop.l = 0; + sd->crop.r = 0; + scale = (double)iw / w; + th = h * scale; + dh = ih - th; + sd->crop.t = sd->crop.b = dh / 2; + } + else if (aspect_opt == 2) // keep height + { + int tw, dw; + double scale; + + sd->crop.t = 0; + sd->crop.b = 0; + scale = (double)ih / h; + tw = w * scale; + dw = iw - tw; + sd->crop.l = sd->crop.r = dw / 2; + } + + _emotion_aspect_borders_apply(obj, sd, w, h, iw, ih); +} + +EAPI void +emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b) +{ + Smart_Data *sd; + int w, h; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + + sd->aspect = EMOTION_ASPECT_CUSTOM; + sd->crop.l = -l; + sd->crop.r = -r; + sd->crop.t = -t; + sd->crop.b = -b; + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + _emotion_object_aspect_border_apply(obj, sd, w, h); +} + +EAPI void +emotion_object_border_get(const Evas_Object *obj, int *l, int *r, int *t, int *b) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + *l = -sd->crop.l; + *r = -sd->crop.r; + *t = -sd->crop.t; + *b = -sd->crop.b; +} + +EAPI void +emotion_object_bg_color_set(Evas_Object *obj, int r, int g, int b, int a) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + + evas_object_color_set(sd->bg, r, g, b, a); + + if (!evas_object_visible_get(obj)) + return; + + if (a > 0) + evas_object_show(sd->bg); + else + evas_object_hide(sd->bg); +} + +EAPI void +emotion_object_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + evas_object_color_get(sd->bg, r, g, b, a); +} + +EAPI void +emotion_object_keep_aspect_set(Evas_Object *obj, Emotion_Aspect a) +{ + Smart_Data *sd; + int w, h; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + + if (a == sd->aspect) + return; + + sd->aspect = a; + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + _emotion_object_aspect_border_apply(obj, sd, w, h); +} + +EAPI Emotion_Aspect +emotion_object_keep_aspect_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_ASPECT_KEEP_NONE); + + return sd->aspect; +} + +EAPI void +emotion_object_play_set(Evas_Object *obj, Eina_Bool play) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("play=" FMT_UCHAR ", was=" FMT_UCHAR, play, sd->play); + if (play == sd->play) return; + if (!sd->module) return; + if (!sd->video_data) return; + if (!sd->open) + { + sd->remember_play = play; + return; + } + sd->play = play; + sd->remember_play = play; + if (sd->state != EMOTION_WAKEUP) emotion_object_suspend_set(obj, EMOTION_WAKEUP); + if (sd->play) sd->module->play(sd->video_data, sd->pos); + else sd->module->stop(sd->video_data); +} + +EAPI Eina_Bool +emotion_object_play_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->video_data) return EINA_FALSE; + + return sd->play; +} + +EAPI void +emotion_object_position_set(Evas_Object *obj, double sec) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("sec=%f", sec); + if (!sd->module) return; + if (!sd->video_data) return; + if (!sd->open) + { + sd->remember_jump = sec; + return ; + } + sd->remember_jump = 0; + sd->seek_pos = sec; + sd->seek = 1; + sd->pos = sd->seek_pos; + if (sd->job) ecore_job_del(sd->job); + sd->job = ecore_job_add(_pos_set_job, obj); +} + +EAPI double +emotion_object_position_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0.0); + if (!sd->module) return 0.0; + if (!sd->video_data) return 0.0; + if (!sd->module->pos_get) return 0.0; + sd->pos = sd->module->pos_get(sd->video_data); + return sd->pos; +} + +EAPI double +emotion_object_buffer_size_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 1.0); + if (!sd->module) return 1.0; + if (!sd->video_data) return 1.0; + if (!sd->module->buffer_size_get) return 1.0; + return sd->module->buffer_size_get(sd->video_data); +} + +EAPI Eina_Bool +emotion_object_seekable_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return EINA_FALSE; + if (!sd->video_data) return EINA_FALSE; + return sd->module->seekable(sd->video_data); +} + +EAPI Eina_Bool +emotion_object_video_handled_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return EINA_FALSE; + if (!sd->video_data) return EINA_FALSE; + return sd->module->video_handled(sd->video_data); +} + +EAPI Eina_Bool +emotion_object_audio_handled_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return EINA_FALSE; + if (!sd->video_data) return EINA_FALSE; + return sd->module->audio_handled(sd->video_data); +} + +EAPI double +emotion_object_play_length_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0.0); + if (!sd->module) return 0.0; + if (!sd->video_data) return 0.0; + sd->len = sd->module->len_get(sd->video_data); + return sd->len; +} + +EAPI void +emotion_object_size_get(const Evas_Object *obj, int *iw, int *ih) +{ + Smart_Data *sd; + + if (iw) *iw = 0; + if (ih) *ih = 0; + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (iw) *iw = sd->video.w; + if (ih) *ih = sd->video.h; +} + +EAPI void +emotion_object_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + evas_object_image_smooth_scale_set(sd->obj, smooth); +} + +EAPI Eina_Bool +emotion_object_smooth_scale_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + return evas_object_image_smooth_scale_get(sd->obj); +} + +EAPI double +emotion_object_ratio_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 1.0); + if (!sd->module) return 0.0; + if (!sd->video_data) return 0.0; + return sd->ratio; +} + +/* + * Send a control event to the DVD. + */ +EAPI void +emotion_object_event_simple_send(Evas_Object *obj, Emotion_Event ev) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->event_feed(sd->video_data, ev); +} + +EAPI void +emotion_object_audio_volume_set(Evas_Object *obj, double vol) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("vol=%f", vol); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->audio_channel_volume_set(sd->video_data, vol); +} + +EAPI double +emotion_object_audio_volume_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 1.0); + if (!sd->module) return 0.0; + if (!sd->video_data) return 0.0; + return sd->module->audio_channel_volume_get(sd->video_data); +} + +EAPI void +emotion_object_audio_mute_set(Evas_Object *obj, Eina_Bool mute) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("mute=" FMT_UCHAR, mute); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->audio_channel_mute_set(sd->video_data, mute); +} + +EAPI Eina_Bool +emotion_object_audio_mute_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return EINA_FALSE; + if (!sd->video_data) return EINA_FALSE; + return sd->module->audio_channel_mute_get(sd->video_data); +} + +EAPI int +emotion_object_audio_channel_count(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return 0; + if (!sd->video_data) return 0; + return sd->module->audio_channel_count(sd->video_data); +} + +EAPI const char * +emotion_object_audio_channel_name_get(const Evas_Object *obj, int channel) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + if (!sd->module) return NULL; + if (!sd->video_data) return NULL; + return sd->module->audio_channel_name_get(sd->video_data, channel); +} + +EAPI void +emotion_object_audio_channel_set(Evas_Object *obj, int channel) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("channel=%d", channel); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->audio_channel_set(sd->video_data, channel); +} + +EAPI int +emotion_object_audio_channel_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return 0; + if (!sd->video_data) return 0; + return sd->module->audio_channel_get(sd->video_data); +} + +EAPI void +emotion_object_video_mute_set(Evas_Object *obj, Eina_Bool mute) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("mute=" FMT_UCHAR, mute); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->video_channel_mute_set(sd->video_data, mute); +} + +EAPI Eina_Bool +emotion_object_video_mute_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return EINA_FALSE; + if (!sd->video_data) return EINA_FALSE; + return sd->module->video_channel_mute_get(sd->video_data); +} + +EAPI int +emotion_object_video_channel_count(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return EINA_FALSE; + if (!sd->video_data) return EINA_FALSE; + return sd->module->video_channel_count(sd->video_data); +} + +EAPI const char * +emotion_object_video_channel_name_get(const Evas_Object *obj, int channel) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + if (!sd->module) return NULL; + if (!sd->video_data) return NULL; + return sd->module->video_channel_name_get(sd->video_data, channel); +} + +EAPI void +emotion_object_video_channel_set(Evas_Object *obj, int channel) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("channel=%d", channel); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->video_channel_set(sd->video_data, channel); +} + +EAPI int +emotion_object_video_channel_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return 0; + if (!sd->video_data) return 0; + return sd->module->video_channel_get(sd->video_data); +} + +EAPI void +emotion_object_spu_mute_set(Evas_Object *obj, Eina_Bool mute) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("mute=" FMT_UCHAR, mute); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->spu_channel_mute_set(sd->video_data, mute); +} + +EAPI Eina_Bool +emotion_object_spu_mute_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return EINA_FALSE; + if (!sd->video_data) return EINA_FALSE; + return sd->module->spu_channel_mute_get(sd->video_data); +} + +EAPI int +emotion_object_spu_channel_count(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return 0; + if (!sd->video_data) return 0; + return sd->module->spu_channel_count(sd->video_data); +} + +EAPI const char * +emotion_object_spu_channel_name_get(const Evas_Object *obj, int channel) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + if (!sd->module) return NULL; + if (!sd->video_data) return NULL; + return sd->module->spu_channel_name_get(sd->video_data, channel); +} + +EAPI void +emotion_object_spu_channel_set(Evas_Object *obj, int channel) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("channel=%d", channel); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->spu_channel_set(sd->video_data, channel); +} + +EAPI int +emotion_object_spu_channel_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return 0; + if (!sd->video_data) return 0; + return sd->module->spu_channel_get(sd->video_data); +} + +EAPI int +emotion_object_chapter_count(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return 0; + if (!sd->video_data) return 0; + return sd->module->chapter_count(sd->video_data); +} + +EAPI void +emotion_object_chapter_set(Evas_Object *obj, int chapter) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("chapter=%d", chapter); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->chapter_set(sd->video_data, chapter); +} + +EAPI int +emotion_object_chapter_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return 0; + if (!sd->video_data) return 0; + return sd->module->chapter_get(sd->video_data); +} + +EAPI const char * +emotion_object_chapter_name_get(const Evas_Object *obj, int chapter) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + if (!sd->module) return NULL; + if (!sd->video_data) return NULL; + return sd->module->chapter_name_get(sd->video_data, chapter); +} + +EAPI void +emotion_object_play_speed_set(Evas_Object *obj, double speed) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("speed=%f", speed); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->speed_set(sd->video_data, speed); +} + +EAPI double +emotion_object_play_speed_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0.0); + if (!sd->module) return 0.0; + if (!sd->video_data) return 0.0; + return sd->module->speed_get(sd->video_data); +} + +EAPI void +emotion_object_eject(Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (!sd->module) return; + if (!sd->video_data) return; + sd->module->eject(sd->video_data); +} + +EAPI const char * +emotion_object_title_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + return sd->title; +} + +EAPI const char * +emotion_object_progress_info_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + return sd->progress.info; +} + +EAPI double +emotion_object_progress_status_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0.0); + return sd->progress.stat; +} + +EAPI const char * +emotion_object_ref_file_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + return sd->ref.file; +} + +EAPI int +emotion_object_ref_num_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + return sd->ref.num; +} + +EAPI int +emotion_object_spu_button_count_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + return sd->spu.button_num; +} + +EAPI int +emotion_object_spu_button_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + return sd->spu.button; +} + +EAPI const char * +emotion_object_meta_info_get(const Evas_Object *obj, Emotion_Meta_Info meta) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + if (!sd->module) return NULL; + if (!sd->video_data) return NULL; + switch (meta) + { + case EMOTION_META_INFO_TRACK_TITLE: + return sd->module->meta_get(sd->video_data, META_TRACK_TITLE); + case EMOTION_META_INFO_TRACK_ARTIST: + return sd->module->meta_get(sd->video_data, META_TRACK_ARTIST); + case EMOTION_META_INFO_TRACK_ALBUM: + return sd->module->meta_get(sd->video_data, META_TRACK_ALBUM); + case EMOTION_META_INFO_TRACK_YEAR: + return sd->module->meta_get(sd->video_data, META_TRACK_YEAR); + case EMOTION_META_INFO_TRACK_GENRE: + return sd->module->meta_get(sd->video_data, META_TRACK_GENRE); + case EMOTION_META_INFO_TRACK_COMMENT: + return sd->module->meta_get(sd->video_data, META_TRACK_COMMENT); + case EMOTION_META_INFO_TRACK_DISC_ID: + return sd->module->meta_get(sd->video_data, META_TRACK_DISCID); + default: + break; + } + return NULL; +} + +EAPI void +emotion_object_vis_set(Evas_Object *obj, Emotion_Vis visualization) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("visualization=%d", visualization); + if (!sd->module) return; + if (!sd->video_data) return; + if (!sd->module->vis_set) return; + sd->module->vis_set(sd->video_data, visualization); +} + +EAPI Emotion_Vis +emotion_object_vis_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_VIS_NONE); + if (!sd->module) return EMOTION_VIS_NONE; + if (!sd->video_data) return EMOTION_VIS_NONE; + if (!sd->module->vis_get) return EMOTION_VIS_NONE; + return sd->module->vis_get(sd->video_data); +} + +EAPI Eina_Bool +emotion_object_vis_supported(const Evas_Object *obj, Emotion_Vis visualization) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return EINA_FALSE; + if (!sd->video_data) return EINA_FALSE; + if (!sd->module->vis_supported) return EINA_FALSE; + return sd->module->vis_supported(sd->video_data, visualization); +} + +EAPI void +emotion_object_priority_set(Evas_Object *obj, Eina_Bool priority) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (!sd->module) return ; + if (!sd->video_data) return ; + if (!sd->module->priority_set) return ; + sd->module->priority_set(sd->video_data, priority); +} + +EAPI Eina_Bool +emotion_object_priority_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0); + if (!sd->module) return EINA_FALSE; + if (!sd->video_data) return EINA_FALSE; + if (!sd->module->priority_get) return EINA_FALSE; + return sd->module->priority_get(sd->video_data); +} + +#ifdef HAVE_EIO +static void +_eio_load_xattr_cleanup(Smart_Data *sd, Eio_File *handler) +{ + if (handler == sd->load_xattr) sd->load_xattr = NULL; + + EINA_REFCOUNT_UNREF(sd) + _smart_data_free(sd); +} + +static void +_eio_load_xattr_done(void *data, Eio_File *handler, double xattr_double) +{ + Smart_Data *sd = data; + + emotion_object_position_set(evas_object_smart_parent_get(sd->obj), xattr_double); + evas_object_smart_callback_call(evas_object_smart_parent_get(sd->obj), SIG_POSITION_LOAD_SUCCEED, NULL); + _eio_load_xattr_cleanup(sd, handler); +} + +static void +_eio_load_xattr_error(void *data, Eio_File *handler, int err __UNUSED__) +{ + Smart_Data *sd = data; + + evas_object_smart_callback_call(evas_object_smart_parent_get(sd->obj), SIG_POSITION_LOAD_FAILED, NULL); + _eio_load_xattr_cleanup(sd, handler); +} +#endif + +EAPI void +emotion_object_last_position_load(Evas_Object *obj) +{ + Smart_Data *sd; + const char *tmp; +#ifndef HAVE_EIO + double xattr; +#endif + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (!sd->file) return ; + + if (!strncmp(sd->file, "file://", 7)) + tmp = sd->file + 7; + else if (!strstr(sd->file, "://")) + tmp = sd->file; + else + return ; + +#ifdef HAVE_EIO + if (sd->load_xattr) return ; + + EINA_REFCOUNT_REF(sd); + + sd->load_xattr = eio_file_xattr_double_get(tmp, + "user.e.time_seek", + _eio_load_xattr_done, + _eio_load_xattr_error, + sd); +#else + if (eina_xattr_double_get(tmp, "user.e.time_seek", &xattr)) + { + emotion_object_position_set(obj, xattr); + evas_object_smart_callback_call(obj, SIG_POSITION_LOAD_SUCCEED, NULL); + } + else + { + evas_object_smart_callback_call(obj, SIG_POSITION_LOAD_FAILED, NULL); + } +#endif +} + +#ifdef HAVE_EIO +static void +_eio_save_xattr_cleanup(Smart_Data *sd, Eio_File *handler) +{ + if (handler == sd->save_xattr) sd->save_xattr = NULL; + + EINA_REFCOUNT_UNREF(sd) + _smart_data_free(sd); +} + +static void +_eio_save_xattr_done(void *data, Eio_File *handler) +{ + Smart_Data *sd = data; + + evas_object_smart_callback_call(sd->obj, SIG_POSITION_SAVE_SUCCEED, NULL); + _eio_save_xattr_cleanup(sd, handler); +} + +static void +_eio_save_xattr_error(void *data, Eio_File *handler, int err __UNUSED__) +{ + Smart_Data *sd = data; + + evas_object_smart_callback_call(sd->obj, SIG_POSITION_SAVE_FAILED, NULL); + _eio_save_xattr_cleanup(sd, handler); +} +#endif + +EAPI void +emotion_object_last_position_save(Evas_Object *obj) +{ + Smart_Data *sd; + const char *tmp; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (!sd->file) return ; + + if (!strncmp(sd->file, "file://", 7)) + tmp = sd->file + 7; + else if (!strstr(sd->file, "://")) + tmp = sd->file; + else + return ; + +#ifdef HAVE_EIO + if (sd->save_xattr) return ; + + EINA_REFCOUNT_REF(sd); + + sd->save_xattr = eio_file_xattr_double_set(tmp, + "user.e.time_seek", + emotion_object_position_get(obj), + 0, + _eio_save_xattr_done, + _eio_save_xattr_error, + sd); +#else + if (eina_xattr_double_set(tmp, "user.e.time_seek", emotion_object_position_get(obj), 0)) + evas_object_smart_callback_call(obj, SIG_POSITION_SAVE_SUCCEED, NULL); + else + evas_object_smart_callback_call(obj, SIG_POSITION_SAVE_FAILED, NULL); +#endif +} + +EAPI void +emotion_object_suspend_set(Evas_Object *obj, Emotion_Suspend state) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + switch (state) + { + case EMOTION_WAKEUP: + /* Restore the rendering pipeline, offset and everything back to play again (this will be called automatically by play_set) */ + case EMOTION_SLEEP: + /* This destroy some part of the rendering pipeline */ + case EMOTION_DEEP_SLEEP: + /* This destroy all the rendering pipeline and just keep the last rendered image (fullscreen) */ + case EMOTION_HIBERNATE: + /* This destroy all the rendering pipeline and keep 1/4 of the last rendered image */ + default: + break; + } + + sd->state = state; +} + +EAPI Emotion_Suspend +motion_object_suspend_get(Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_WAKEUP); + return sd->state; +} + +/*****************************/ +/* Utility calls for modules */ +/*****************************/ + +EAPI void * +_emotion_video_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL); + return sd->video_data; +} + +static Eina_Bool +_emotion_frame_anim(void *data) +{ + Evas_Object *obj = data; + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EINA_FALSE); + + evas_object_image_pixels_dirty_set(sd->obj, 1); + evas_object_smart_callback_call(obj, SIG_FRAME_DECODE, NULL); + sd->anim = NULL; + + return EINA_FALSE; +} + +EAPI void +_emotion_frame_new(Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + + if (!sd->anim) sd->anim = ecore_animator_add(_emotion_frame_anim, obj); +} + +EAPI void +_emotion_video_pos_update(Evas_Object *obj, double pos, double len) +{ + Smart_Data *sd; + int npos = 0, nlen = 0; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (pos != sd->pos) npos = 1; + if (len != sd->len) nlen = 1; + sd->pos = pos; + sd->len = len; + if (npos) evas_object_smart_callback_call(obj, SIG_POSITION_UPDATE, NULL); + if (nlen) evas_object_smart_callback_call(obj, SIG_LENGTH_CHANGE, NULL); +} + +EAPI void +_emotion_frame_resize(Evas_Object *obj, int w, int h, double ratio) +{ + Smart_Data *sd; + double tmp; + int changed = 0; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if ((w != sd->video.w) || (h != sd->video.h)) + { + sd->video.w = w; + sd->video.h = h; + _emotion_image_data_zero(sd->obj); + changed = 1; + } + if (h > 0) tmp = (double)w / (double)h; + else tmp = 1.0; + if (ratio != tmp) tmp = ratio; + if (tmp != sd->ratio) + { + sd->ratio = tmp; + changed = 1; + } + if (changed) + { + evas_object_size_hint_request_set(obj, w, h); + evas_object_smart_callback_call(obj, SIG_FRAME_RESIZE, NULL); + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + _emotion_object_aspect_border_apply(obj, sd, w, h); + } +} + +EAPI void +_emotion_image_reset(Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + _emotion_image_data_zero(sd->obj); +} + +EAPI void +_emotion_decode_stop(Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (sd->play) + { + sd->play = 0; + evas_object_smart_callback_call(obj, SIG_DECODE_STOP, NULL); + } +} + +EAPI void +_emotion_open_done(Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + sd->open = 1; + + if (sd->remember_jump) + emotion_object_position_set(obj, sd->remember_jump); + if (sd->remember_play != sd->play) + emotion_object_play_set(obj, sd->remember_play); + evas_object_smart_callback_call(obj, SIG_OPEN_DONE, NULL); +} + +EAPI void +_emotion_playback_started(Evas_Object *obj) +{ + evas_object_smart_callback_call(obj, SIG_PLAYBACK_STARTED, NULL); +} + +EAPI void +_emotion_playback_finished(Evas_Object *obj) +{ + evas_object_smart_callback_call(obj, SIG_PLAYBACK_FINISHED, NULL); +} + +EAPI void +_emotion_audio_level_change(Evas_Object *obj) +{ + evas_object_smart_callback_call(obj, SIG_AUDIO_LEVEL_CHANGE, NULL); +} + +EAPI void +_emotion_channels_change(Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + evas_object_smart_callback_call(obj, SIG_CHANNELS_CHANGE, NULL); +} + +EAPI void +_emotion_title_set(Evas_Object *obj, char *title) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + free(sd->title); + sd->title = strdup(title); + evas_object_smart_callback_call(obj, SIG_TITLE_CHANGE, NULL); +} + +EAPI void +_emotion_progress_set(Evas_Object *obj, char *info, double st) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + free(sd->progress.info); + sd->progress.info = strdup(info); + sd->progress.stat = st; + evas_object_smart_callback_call(obj, SIG_PROGRESS_CHANGE, NULL); +} + +EAPI void +_emotion_file_ref_set(Evas_Object *obj, const char *file, int num) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + free(sd->ref.file); + sd->ref.file = strdup(file); + sd->ref.num = num; + evas_object_smart_callback_call(obj, SIG_REF_CHANGE, NULL); +} + +EAPI void +_emotion_spu_button_num_set(Evas_Object *obj, int num) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + sd->spu.button_num = num; + evas_object_smart_callback_call(obj, SIG_BUTTON_NUM_CHANGE, NULL); +} + +EAPI void +_emotion_spu_button_set(Evas_Object *obj, int button) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + sd->spu.button = button; + evas_object_smart_callback_call(obj, SIG_BUTTON_CHANGE, NULL); +} + +EAPI void +_emotion_seek_done(Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (sd->seeking) + { + sd->seeking = 0; + if (sd->seek) emotion_object_position_set(obj, sd->seek_pos); + } +} + +EAPI void +_emotion_frame_refill(Evas_Object *obj, double w, double h) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + if (sd->fill.w != w || sd->fill.h != h) + { + Evas_Coord ow, oh; + + evas_object_geometry_get(obj, NULL, NULL, &ow, &oh); + if (w <= 0 || h <= 0) + { + double scale_w, scale_h; + + sd->fill.w = -1; + sd->fill.h = -1; + + scale_w = (double) ow / (double)(sd->video.w - sd->crop.l - sd->crop.r); + scale_h = (double) oh / (double)(sd->video.h - sd->crop.t - sd->crop.b); + + evas_object_image_fill_set(sd->obj, 0, 0, scale_w * sd->video.w, scale_h * sd->video.h); + } + else + { + sd->fill.w = w; + sd->fill.h = h; + + evas_object_image_fill_set(sd->obj, 0, 0, w * ow, h * oh); + } + } +} + +/****************************/ +/* Internal object routines */ +/****************************/ + +static void +_mouse_move(void *data, Evas *ev __UNUSED__, Evas_Object *obj, void *event_info) +{ + Evas_Event_Mouse_Move *e; + Smart_Data *sd; + int x, y, iw, ih; + Evas_Coord ox, oy, ow, oh; + + e = event_info; + sd = data; + if (!sd->module) return; + if (!sd->video_data) return; + evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); + evas_object_image_size_get(obj, &iw, &ih); + if ((iw < 1) || (ih < 1)) return; + x = (((int)e->cur.canvas.x - ox) * iw) / ow; + y = (((int)e->cur.canvas.y - oy) * ih) / oh; + sd->module->event_mouse_move_feed(sd->video_data, x, y); +} + +static void +_mouse_down(void *data, Evas *ev __UNUSED__, Evas_Object *obj, void *event_info) +{ + Evas_Event_Mouse_Down *e; + Smart_Data *sd; + int x, y, iw, ih; + Evas_Coord ox, oy, ow, oh; + + e = event_info; + sd = data; + if (!sd->module) return; + if (!sd->video_data) return; + evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); + evas_object_image_size_get(obj, &iw, &ih); + if ((iw < 1) || (ih < 1)) return; + x = (((int)e->canvas.x - ox) * iw) / ow; + y = (((int)e->canvas.y - oy) * ih) / oh; + sd->module->event_mouse_button_feed(sd->video_data, 1, x, y); +} + +static void +_pos_set_job(void *data) +{ + Evas_Object *obj; + Smart_Data *sd; + + obj = data; + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + sd->job = NULL; + if (sd->seeking) return; + if (sd->seek) + { + sd->seeking = 1; + sd->module->pos_set(sd->video_data, sd->seek_pos); + sd->seek = 0; + } +} + +/* called by evas when it needs pixels for the image object */ +static void +_pixels_get(void *data, Evas_Object *obj) +{ + int iw, ih, w, h; + Smart_Data *sd; + Emotion_Format format; + unsigned char *bgra_data; + + sd = data; + sd->module->video_data_size_get(sd->video_data, &w, &h); + w = (w >> 1) << 1; + h = (h >> 1) << 1; + + evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_YCBCR422P601_PL); + evas_object_image_alpha_set(obj, 0); + evas_object_image_size_set(obj, w, h); + iw = w; + ih = h; + + if ((iw <= 1) || (ih <= 1)) + { + _emotion_image_data_zero(sd->obj); + evas_object_image_pixels_dirty_set(obj, 0); + } + else + { + format = sd->module->format_get(sd->video_data); + if ((format == EMOTION_FORMAT_YV12) || (format == EMOTION_FORMAT_I420)) + { + unsigned char **rows; + + evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_YCBCR422P601_PL); + rows = evas_object_image_data_get(obj, 1); + if (rows) + { + if (sd->module->yuv_rows_get(sd->video_data, iw, ih, + rows, + &rows[ih], + &rows[ih + (ih / 2)])) + evas_object_image_data_update_add(obj, 0, 0, iw, ih); + } + evas_object_image_data_set(obj, rows); + evas_object_image_pixels_dirty_set(obj, 0); + } + else if (format == EMOTION_FORMAT_BGRA) + { + evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_ARGB8888); + if (sd->module->bgra_data_get(sd->video_data, &bgra_data)) + { + evas_object_image_data_set(obj, bgra_data); + evas_object_image_pixels_dirty_set(obj, 0); + } + } + } +} + +/*******************************************/ +/* Internal smart object required routines */ +/*******************************************/ +#ifdef EMOTION_STATIC_BUILD_XINE +Eina_Bool xine_module_init(void); +#endif +#ifdef EMOTION_STATIC_BUILD_GSTREAMER +Eina_Bool gstreamer_module_init(void); +#endif +#ifdef EMOTION_STATIC_BUILD_GENERIC +Eina_Bool generic_module_init(void); +#endif + +static void +_smart_init(void) +{ + char *path; + + if (smart) return; + { + eina_init(); + + _log_domain = eina_log_domain_register("emotion", EINA_COLOR_LIGHTCYAN); + if (_log_domain < 0) + { + EINA_LOG_CRIT("Could not register log domain 'emotion'"); + eina_shutdown(); + return; + } + + _backends = eina_hash_string_small_new(free); + + _modules = eina_module_list_get(NULL, PACKAGE_LIB_DIR "/emotion/", 0, NULL, NULL); + + path = eina_module_environment_path_get("HOME", "/.emotion/"); + _modules = eina_module_list_get(_modules, path, 0, NULL, NULL); + if (path) free(path); + + path = eina_module_environment_path_get("EMOTION_MODULES_DIR", "/emotion/"); + _modules = eina_module_list_get(_modules, path, 0, NULL, NULL); + if (path) free(path); + + path = eina_module_symbol_path_get(emotion_object_add, "/emotion/"); + _modules = eina_module_list_get(_modules, path, 0, NULL, NULL); + if (path) free(path); + + if (!_modules) + { + ERR("No module found!"); + return; + } + + eina_module_list_load(_modules); + + /* Init static module */ +#ifdef EMOTION_STATIC_BUILD_XINE + xine_module_init(); +#endif +#ifdef EMOTION_STATIC_BUILD_GSTREAMER + gstreamer_module_init(); +#endif +#ifdef EMOTION_STATIC_BUILD_GENERIC + generic_module_init(); +#endif + + static Evas_Smart_Class sc = + EVAS_SMART_CLASS_INIT_NAME_VERSION(E_OBJ_NAME); + if (!sc.add) + { + sc.add = _smart_add; + sc.del = _smart_del; + sc.move = _smart_move; + sc.resize = _smart_resize; + sc.show = _smart_show; + sc.hide = _smart_hide; + sc.color_set = _smart_color_set; + sc.clip_set = _smart_clip_set; + sc.clip_unset = _smart_clip_unset; + sc.callbacks = _smart_callbacks; + } + smart = evas_smart_class_new(&sc); + } +} + +static void +_smart_add(Evas_Object * obj) +{ + Smart_Data *sd; + unsigned int *pixel; + + sd = calloc(1, sizeof(Smart_Data)); + if (!sd) return; + EINA_REFCOUNT_INIT(sd); + sd->state = EMOTION_WAKEUP; + sd->obj = evas_object_image_add(evas_object_evas_get(obj)); + sd->bg = evas_object_rectangle_add(evas_object_evas_get(obj)); + evas_object_color_set(sd->bg, 0, 0, 0, 0); + evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, sd); + evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, sd); + evas_object_image_pixels_get_callback_set(sd->obj, _pixels_get, sd); + evas_object_smart_member_add(sd->obj, obj); + evas_object_smart_member_add(sd->bg, obj); + evas_object_lower(sd->bg); + sd->ratio = 1.0; + sd->spu.button = -1; + sd->fill.w = -1; + sd->fill.h = -1; + evas_object_image_alpha_set(sd->obj, 0); + pixel = evas_object_image_data_get(sd->obj, 1); + if (pixel) + { + *pixel = 0xff000000; + evas_object_image_data_set(obj, pixel); + } + evas_object_smart_data_set(obj, sd); + + ecore_init(); +} + +static void +_smart_del(Evas_Object * obj) +{ + Smart_Data *sd; + + sd = evas_object_smart_data_get(obj); + if (!sd) return; + EINA_REFCOUNT_UNREF(sd) + _smart_data_free(sd); +} + +static void +_smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y) +{ + Smart_Data *sd; + int w, h; + + sd = evas_object_smart_data_get(obj); + if (!sd) return; + + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + _clipper_position_size_update(obj, x, y, w, h, sd->video.w, sd->video.h); + evas_object_move(sd->bg, x, y); +} + +static void +_smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h) +{ + Smart_Data *sd; + + sd = evas_object_smart_data_get(obj); + if (!sd) return; + + _emotion_object_aspect_border_apply(obj, sd, w, h); + evas_object_resize(sd->bg, w, h); +} + +static void +_smart_show(Evas_Object * obj) +{ + Smart_Data *sd; + int a; + + sd = evas_object_smart_data_get(obj); + if (!sd) return; + evas_object_show(sd->obj); + if (sd->crop.clipper) + evas_object_show(sd->crop.clipper); + + evas_object_color_get(sd->bg, NULL, NULL, NULL, &a); + if (a > 0) + evas_object_show(sd->bg); +} + +static void +_smart_hide(Evas_Object * obj) +{ + Smart_Data *sd; + + sd = evas_object_smart_data_get(obj); + if (!sd) return; + evas_object_hide(sd->obj); + if (sd->crop.clipper) + evas_object_hide(sd->crop.clipper); + evas_object_hide(sd->bg); +} + +static void +_smart_color_set(Evas_Object * obj, int r, int g, int b, int a) +{ + Smart_Data *sd; + + sd = evas_object_smart_data_get(obj); + if (!sd) return; + evas_object_color_set(sd->obj, r, g, b, a); + evas_object_color_set(sd->crop.clipper, r, g, b, a); +} + +static void +_smart_clip_set(Evas_Object * obj, Evas_Object * clip) +{ + Smart_Data *sd; + + sd = evas_object_smart_data_get(obj); + if (!sd) return; + if (sd->crop.clipper) + evas_object_clip_set(sd->crop.clipper, clip); + else + evas_object_clip_set(sd->obj, clip); + evas_object_clip_set(sd->bg, clip); +} + +static void +_smart_clip_unset(Evas_Object * obj) +{ + Smart_Data *sd; + + sd = evas_object_smart_data_get(obj); + if (!sd) return; + if (sd->crop.clipper) + evas_object_clip_unset(sd->crop.clipper); + else + evas_object_clip_unset(sd->obj); + evas_object_clip_unset(sd->bg); +} + diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am new file mode 100644 index 0000000..faaa146 --- /dev/null +++ b/src/modules/Makefile.am @@ -0,0 +1,4 @@ + +MAINTAINERCLEANFILES = Makefile.in + +SUBDIRS = xine gstreamer generic diff --git a/src/modules/generic/Emotion_Generic_Plugin.h b/src/modules/generic/Emotion_Generic_Plugin.h new file mode 100644 index 0000000..17bd7e9 --- /dev/null +++ b/src/modules/generic/Emotion_Generic_Plugin.h @@ -0,0 +1,144 @@ +#ifndef EMOTION_GENERIC_PLUGIN_H +#define EMOTION_GENERIC_PLUGIN_H + +#include +#include +#include +#include +#include + +#include + +#define DEFAULTWIDTH 320 +#define DEFAULTHEIGHT 240 +#define DEFAULTPITCH 4 + +typedef enum _Emotion_Generic_Cmd Emotion_Generic_Cmd; +typedef enum _Emotion_Generic_Result Emotion_Generic_Result; +typedef struct _Emotion_Generic_Video_Frame Emotion_Generic_Video_Frame; +typedef struct _Emotion_Generic_Video_Shared Emotion_Generic_Video_Shared; + +enum _Emotion_Generic_Cmd +{ + EM_CMD_INIT = 0, // param: shared memory identifier (string) + EM_CMD_PLAY, // param: position (float) + EM_CMD_STOP, // param: none + EM_CMD_FILE_SET, // param: filename (string) + EM_CMD_FILE_SET_DONE, // param: success (int) + EM_CMD_FILE_CLOSE, // param: none + EM_CMD_POSITION_SET, // param: position (float) + EM_CMD_SPEED_SET, // param: speed (float) + EM_CMD_AUDIO_MUTE_SET, // param: muted (int) + EM_CMD_VIDEO_MUTE_SET, // param: muted (int) + EM_CMD_SPU_MUTE_SET, // param: muted (int) + EM_CMD_VOLUME_SET, // param: volume (float) + EM_CMD_AUDIO_TRACK_SET, // param: track id (int) + EM_CMD_VIDEO_TRACK_SET, // param: track id (int) + EM_CMD_SPU_TRACK_SET, // param: track id (int) + EM_CMD_LAST +}; + +enum _Emotion_Generic_Result +{ + EM_RESULT_INIT = 0, // param: none + EM_RESULT_FILE_SET, // param: none + EM_RESULT_FILE_SET_DONE, // param: success (int) + EM_RESULT_PLAYBACK_STARTED, // param: none + EM_RESULT_PLAYBACK_STOPPED, // param: none + EM_RESULT_FILE_CLOSE, // param: none + EM_RESULT_FRAME_NEW, // param: none + EM_RESULT_FRAME_SIZE, // param: int, int (width, height) + EM_RESULT_LENGTH_CHANGED, // param: float + EM_RESULT_POSITION_CHANGED, // param: float + EM_RESULT_SEEKABLE_CHANGED, // param: int + EM_RESULT_AUDIO_TRACK_INFO, // param: current track, track count, track_id, track_name, track_id2, track_name2, ... + EM_RESULT_VIDEO_TRACK_INFO, // param: current track, track count, track_id, track_name, track_id2, track_name2, ... + EM_RESULT_SPU_TRACK_INFO, // param: current spu, spu count, spu_id, spu_name, spu_id2, spu_name2, ... + // (int, int, int, string, int, string, ...) + EM_RESULT_META_INFO, // param: title, artist, album, year, genre, comments, disc id, count (all int) + EM_RESULT_LAST +}; + +/* structure for frames 2 buffers to keep integrity */ +struct _Emotion_Generic_Video_Frame +{ + unsigned char *frames[3]; +}; + +/* structure for frames 2 buffers to keep integrity */ +struct _Emotion_Generic_Video_Shared +{ + int size; + int width; + int height; + int pitch; + /** + * - "emotion" is the frame from where the Emotion process is reading pixels. + * The player shouldn't touch this frame. + * - "player" is the frame where the slayer process is writing pixels. + * The emotion process shouldn't touch this frame. + * - "last" is the last frame that was rendered by the player. Emotion will + * use this frame the next time it will fetch pixels to Evas. + * - "next" is the unused frame. The player currently using the "player" + * should, after finishing this frame, set "last" to "player", and "player" + * to "next", and finally "next" to "last" so this operation can be done + * many times in case that Emotion does not request pixels fast enough. + */ + struct { + int emotion; + int player; + int last; + int next; + } frame; + Eina_Semaphore lock; + int frame_drop; +}; + +static inline int +emotion_generic_shm_get(const char *shmname, Emotion_Generic_Video_Shared **vs, Emotion_Generic_Video_Frame *vf) +{ + int shmfd = -1; + int size; + Emotion_Generic_Video_Shared *t_vs; + + shmfd = shm_open(shmname, O_RDWR, 0777); + if (shmfd == -1) + { + fprintf(stderr, "player: could not open shm: %s\n", shmname); + fprintf(stderr, "player: %s\n", strerror(errno)); + return 0; + } + + t_vs = mmap(NULL, sizeof(*t_vs), PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0); + if (t_vs == MAP_FAILED) + { + fprintf(stderr, "player: could not map shared memory.\n"); + fprintf(stderr, "player: %s\n", strerror(errno)); + return 0; + } + size = t_vs->size; + munmap(t_vs, sizeof(*t_vs)); + t_vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0); + if (t_vs == MAP_FAILED) + { + fprintf(stderr, "player: could not map shared memory.\n"); + fprintf(stderr, "player: %s\n", strerror(errno)); + return 0; + } + + vf->frames[0] = (unsigned char *)t_vs + sizeof(*t_vs); + vf->frames[1] = (unsigned char *)t_vs + sizeof(*t_vs) + t_vs->height * t_vs->width * t_vs->pitch; + vf->frames[2] = (unsigned char *)t_vs + sizeof(*t_vs) + 2 * t_vs->height * t_vs->width * t_vs->pitch; + + *vs = t_vs; + + return 1; +} + +static inline void +emotion_generic_shm_free(Emotion_Generic_Video_Shared *vs) +{ + munmap(vs, vs->size); +} + +#endif // EMOTION_GENERIC_PLUGIN_H diff --git a/src/modules/generic/Makefile.am b/src/modules/generic/Makefile.am new file mode 100644 index 0000000..23be987 --- /dev/null +++ b/src/modules/generic/Makefile.am @@ -0,0 +1,31 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/modules \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EMOTION_CFLAGS@ \ +@EMOTION_CPPFLAGS@ \ +@EFL_EMOTION_BUILD@ + +if EMOTION_BUILD_GENERIC +if !EMOTION_STATIC_BUILD_GENERIC + +pkgdir = $(libdir)/emotion + +pkg_LTLIBRARIES = em_generic.la +includes_HEADERS = Emotion_Generic_Plugin.h +includesdir = $(includedir)/emotion-@VMAJ@ +noinst_HEADERS = emotion_generic.h + +em_generic_la_SOURCES = emotion_generic.c +em_generic_la_LIBADD = @EMOTION_LIBS@ @EFL_SHM_OPEN_LIBS@ $(top_builddir)/src/lib/libemotion.la +em_generic_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +em_generic_la_LIBTOOLFLAGS = --tag=disable-static +em_generic_la_DEPENDENCIES = emotion_generic.h Emotion_Generic_Plugin.h + +endif +endif diff --git a/src/modules/generic/README b/src/modules/generic/README new file mode 100644 index 0000000..c2a028d --- /dev/null +++ b/src/modules/generic/README @@ -0,0 +1,79 @@ +Generic - emotion backend +========================= + +This generic player backend executes a separate player in another +process. It receives the bytes to be drawn on the emotion object through +a shared memory, and communicates with the player through a pipe, using +the player standard input/output. + +The player must communicate with emotion using the defined commands +specified in the Emotion_Generic_Plugin.h. It doesn't need to link +against emotion, just include this file for easier implementation. + + +How does it work? +================= + +When the module is initialized for an emotion object, it starts another process +that runs the specified player. The player command line is specified using: + + emotion_object_module_option_set(object, "player", ); + +A player using libvlc is being provided now, and the generic module internally +checks if the command given was "vlc", in which case it will use this provided +vlc player. + +When a file is set to this object, it will send the file name to the player, and +expect an answer that will tell that the player already decoded a bit of the +file, and the video size is already set on the module, so it can allocate a +shared memory with correct size. + +The module then allocates the memory, sends a message to the player and expect +an answer. After this last answer, the "open_done" signal is sent and the module +knows that it is ready for playing. Commands sent before the module being ready +are now applied (and play is resumed if necessary). + +During this setup stage, info about the file set will be stored in the module, +so commands like meta data get, length get and so will be available to sync +calls like emotion_object_play_length_get(); + +If the player dies for any reason, a "decode_stop" signal is sent (should change +to something more like an error signal), and if play is called again, it will be +restarted. The playback should start from the same point it was before the +player crashed, if the player supports seek on the current media format). + +TODO +==== + + - Provide better description for commands; + - Explain in details the communication emotion <-> player; + - Make more common functions for players; + - (maybe) add support for named pipes, so we don't rely on standard in/out + for communication; + - Add a detection on the player to know that the emotion process died (so it + can just exit); + - shmname should contain the child pid too; + - better names for commands, maybe add namespace everywhere; + + +questions +========= + + - Using semaphores to lock the critical region between process, and pthread + mutexes for the threads inside the player. Should move to only one type + (semphores or mutexes)? + - There are 2 inline functions insde Emotion_Generic_Plugin.h to make it easier + for the player to get the shared memory correctly. Any problem with this? + Would be good to add more functions/macros to make common tasks like + parsing commands there too? + - Should move players to another project (outside of emotion)? + + +problems +======== + - file_set has some critical time when file is not set yet when we can't call + some functions (I think only another file_set now); + - communication player -> emotion depends on '\n' to delimitate commands, will + remove this soon (fix this urgently!); + - need to implement missing APIs; + diff --git a/src/modules/generic/emotion_generic.c b/src/modules/generic/emotion_generic.c new file mode 100644 index 0000000..e4771ce --- /dev/null +++ b/src/modules/generic/emotion_generic.c @@ -0,0 +1,1794 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Emotion.h" +#include "emotion_private.h" +#include "emotion_generic.h" + +static Eina_Prefix *pfx = NULL; + +static int _emotion_generic_log_domain = -1; +#define DBG(...) EINA_LOG_DOM_DBG(_emotion_generic_log_domain, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(_emotion_generic_log_domain, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(_emotion_generic_log_domain, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(_emotion_generic_log_domain, __VA_ARGS__) +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_emotion_generic_log_domain, __VA_ARGS__) + + +struct _default_players { + const char *name; + const char *cmdline; +}; + +static struct _default_players players[] = { +#ifdef EMOTION_BUILD_GENERIC_VLC + { "vlc", "em_generic_vlc" }, +#endif + { NULL, NULL } +}; + +static Eina_Bool _fork_and_exec(Emotion_Generic_Video *ev); +static void em_partial_shutdown(Emotion_Generic_Video *ev); + +static Eina_Bool +_player_restart(void *data) +{ + Emotion_Generic_Video *ev = data; + + _fork_and_exec(ev); + ev->player_restart = NULL; + return EINA_FALSE; +} + +static const char * +_get_player(const char *name) +{ + const char *selected_name = NULL; + const char *libdir = eina_prefix_lib_get(pfx); + static char buf[PATH_MAX]; + int i; + + if (name) + { + for (i = 0; players[i].name; i++) + { + if (!strcmp(players[i].name, name)) + { + selected_name = players[i].cmdline; + break; + } + } + } + + if ((!selected_name) && (name)) + selected_name = name; + + if (selected_name) + { + const char *cmd; + + if (selected_name[0] == '/') cmd = selected_name; + else + { + snprintf(buf, sizeof(buf), "%s/emotion/utils/%s", + libdir, selected_name); + cmd = buf; + } + + DBG("Try generic player '%s'", cmd); + if (access(cmd, R_OK | X_OK) == 0) + { + INF("Using generic player '%s'", cmd); + return cmd; + } + } + + for (i = 0; players[i].name; i++) + { + snprintf(buf, sizeof(buf), "%s/emotion/utils/%s", + libdir, players[i].cmdline); + DBG("Try generic player '%s'", buf); + if (access(buf, R_OK | X_OK) == 0) + { + INF("Using fallback player '%s'", buf); + return buf; + } + } + + ERR("no generic player found, given name='%s'", name ? name : ""); + return NULL; +} + +static void +_player_send_cmd(Emotion_Generic_Video *ev, int cmd) +{ + if (cmd >= EM_CMD_LAST) + { + ERR("invalid command to player."); + return; + } + if (ev->fd_write == -1) + { + ERR("you should wait for emotion to be ready to take action."); + return ; + } + if (write(ev->fd_write, &cmd, sizeof(cmd)) < 0) perror("write"); +} + +static void +_player_send_int(Emotion_Generic_Video *ev, int number) +{ + if (ev->fd_write == -1) + { + ERR("you should wait for emotion to be ready to take action."); + return ; + } + if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write"); +} + +static void +_player_send_float(Emotion_Generic_Video *ev, float number) +{ + if (ev->fd_write == -1) + { + ERR("you should wait for emotion to be ready to take action."); + return ; + } + if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write"); +} + +static void +_player_send_str(Emotion_Generic_Video *ev, const char *str, Eina_Bool stringshared) +{ + int len; + + if (stringshared) + len = eina_stringshare_strlen(str) + 1; + else + len = strlen(str) + 1; + if (write(ev->fd_write, &len, sizeof(len)) < 0) perror("write"); + if (write(ev->fd_write, str, len) < 0) perror("write"); +} + +static Eina_Bool +_create_shm_data(Emotion_Generic_Video *ev, const char *shmname) +{ + int shmfd; + int npages; + size_t size; + Emotion_Generic_Video_Shared *vs; + + shmfd = shm_open(shmname, O_CREAT | O_RDWR | O_TRUNC, 0777); + if (shmfd == -1) + { + ERR("player: could not open shm: %s", shmname); + ERR("player: %s", strerror(errno)); + return 0; + } + size = 3 * (ev->w * ev->h * DEFAULTPITCH) + sizeof(*vs); + + npages = (int)(size / getpagesize()) + 1; + size = npages * getpagesize(); + + if (ftruncate(shmfd, size)) + { + ERR("error when allocating shared memory (size = %zd): " + "%s", size, strerror(errno)); + shm_unlink(shmname); + return EINA_FALSE; + } + vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0); + if (vs == MAP_FAILED) + { + ERR("error when mapping shared memory"); + return EINA_FALSE; + } + + vs->size = size; + vs->width = ev->w; + vs->height = ev->h; + vs->pitch = DEFAULTPITCH; + vs->frame.emotion = 0; + vs->frame.player = 1; + vs->frame.last = 2; + vs->frame.next = 2; + vs->frame_drop = 0; + if (!eina_semaphore_new(&vs->lock, 1)) + { + ERR("can not create semaphore"); + return EINA_FALSE; + } + ev->frame.frames[0] = (unsigned char *)vs + sizeof(*vs); + ev->frame.frames[1] = (unsigned char *)vs + sizeof(*vs) + vs->height * vs->width * vs->pitch; + ev->frame.frames[2] = (unsigned char *)vs + sizeof(*vs) + 2 * vs->height * vs->width * vs->pitch; + + if (ev->shared) + munmap(ev->shared, ev->shared->size); + ev->shared = vs; + + return EINA_TRUE; +} + +static void +_player_new_frame(Emotion_Generic_Video *ev) +{ + if (!ev->file_ready) + return; + _emotion_frame_new(ev->obj); +} + +static void +_file_open(Emotion_Generic_Video *ev) +{ + INF("Opening file: %s", ev->filename); + ev->drop = 0; + + if (!ev->ready || !ev->filename) + return; + _player_send_cmd(ev, EM_CMD_FILE_SET); + _player_send_str(ev, ev->filename, EINA_TRUE); +} + +static void +_player_file_set_done(Emotion_Generic_Video *ev) +{ + if (ev->file_changed) + { + _file_open(ev); + ev->file_changed = EINA_FALSE; + return; + } + + if (!_create_shm_data(ev, ev->shmname)) + { + ERR("could not create shared memory."); + return; + } + _player_send_cmd(ev, EM_CMD_FILE_SET_DONE); +} + +static void +_player_ready(Emotion_Generic_Video *ev) +{ + INF("received: player ready."); + + ev->initializing = EINA_FALSE; + ev->ready = EINA_TRUE; + + if (!ev->filename) + return; + + _file_open(ev); +} + +static Eina_Bool +_player_cmd_param_read(Emotion_Generic_Video *ev, void *param, size_t size) +{ + ssize_t done, todo, i; + + /* When a parameter must be read, we cannot make sure it will be entirely + * available. Thus we store the bytes that could be read in a temp buffer, + * and when more data is read we try to complete the buffer and finally use + * the read value. + */ + if (!ev->cmd.tmp) + { + ev->cmd.tmp = malloc(size); + ev->cmd.i = 0; + ev->cmd.total = size; + } + + todo = ev->cmd.total - ev->cmd.i; + i = ev->cmd.i; + done = read(ev->fd_read, &ev->cmd.tmp[i], todo); + + if (done < 0 && errno != EINTR && errno != EAGAIN) + { + if (ev->cmd.tmp) + { + free(ev->cmd.tmp); + ev->cmd.tmp = NULL; + } + ERR("problem when reading parameter from pipe."); + ev->cmd.type = -1; + return EINA_FALSE; + } + + if (done == todo) + { + memcpy(param, ev->cmd.tmp, size); + free(ev->cmd.tmp); + ev->cmd.tmp = NULL; + return EINA_TRUE; + } + + if (done > 0) + ev->cmd.i += done; + + return EINA_FALSE; +} + +static void +_player_frame_resize(Emotion_Generic_Video *ev) +{ + int w, h; + + w = ev->cmd.param.size.width; + h = ev->cmd.param.size.height; + + INF("received frame resize: %dx%d", w, h); + ev->w = w; + ev->h = h; + ev->ratio = (float)w / h; + + if (ev->opening) + return; + + _emotion_frame_resize(ev->obj, ev->w, ev->h, ev->ratio); +} + +static void +_player_length_changed(Emotion_Generic_Video *ev) +{ + float length = ev->cmd.param.f_num; + + INF("received length changed: %0.3f", length); + + ev->len = length; + _emotion_video_pos_update(ev->obj, ev->pos, ev->len); +} + +static void +_player_position_changed(Emotion_Generic_Video *ev) +{ + float position = ev->cmd.param.f_num; + + INF("received position changed: %0.3f", position); + + ev->pos = position; + _emotion_video_pos_update(ev->obj, ev->pos, ev->len); +/* hmmm. no _emotion_progress_set() is for "buffering" progress. + if (ev->len == 0) + return; + + float progress = ev->pos / ev->len; + char buf[16]; + snprintf(buf, sizeof(buf), "%0.1f%%", progress * 100); + + _emotion_progress_set(ev->obj, buf, progress); + */ +} + +static void +_player_seekable_changed(Emotion_Generic_Video *ev) +{ + int seekable = ev->cmd.param.i_num; + + INF("received seekable changed: %d", seekable); + + seekable = !!seekable; + + ev->seekable = seekable; +} + +static void +_audio_channels_free(Emotion_Generic_Video *ev) +{ + int i; + for (i = 0; i < ev->audio_channels_count; i++) + eina_stringshare_del(ev->audio_channels[i].name); + free(ev->audio_channels); + ev->audio_channels = NULL; + ev->audio_channels_count = 0; +} + +static void +_video_channels_free(Emotion_Generic_Video *ev) +{ + int i; + for (i = 0; i < ev->video_channels_count; i++) + eina_stringshare_del(ev->video_channels[i].name); + free(ev->video_channels); + ev->video_channels = NULL; + ev->video_channels_count = 0; +} + +static void +_spu_channels_free(Emotion_Generic_Video *ev) +{ + int i; + for (i = 0; i < ev->spu_channels_count; i++) + eina_stringshare_del(ev->spu_channels[i].name); + free(ev->spu_channels); + ev->spu_channels = NULL; + ev->spu_channels_count = 0; +} + +static void +_player_tracks_info(Emotion_Generic_Video *ev, Emotion_Generic_Channel **channels, int *count, int *current) +{ + Emotion_Generic_Channel *pchannels; + int i; + + *count = ev->cmd.param.track.total; + *current = ev->cmd.param.track.current; + pchannels = ev->cmd.param.track.channels; + + INF("number of tracks: %d (current = %d):", *count, *current); + for (i = 0; i < *count; i++) + { + INF("\tchannel %d: %s", pchannels[i].id, pchannels[i].name); + } + + *channels = pchannels; +} + +static void +_player_audio_tracks_info(Emotion_Generic_Video *ev) +{ + INF("Receiving audio channels:"); + if (ev->audio_channels_count) + _audio_channels_free(ev); + + _player_tracks_info(ev, &ev->audio_channels, &ev->audio_channels_count, + &ev->audio_channel_current); +} + +static void +_player_video_tracks_info(Emotion_Generic_Video *ev) +{ + INF("Receiving video channels:"); + if (ev->video_channels_count) + _video_channels_free(ev); + + _player_tracks_info(ev, &ev->video_channels, &ev->video_channels_count, + &ev->video_channel_current); +} + +static void +_player_spu_tracks_info(Emotion_Generic_Video *ev) +{ + INF("Receiving spu channels:"); + if (ev->spu_channels_count) + _spu_channels_free(ev); + + _player_tracks_info(ev, &ev->spu_channels, &ev->spu_channels_count, + &ev->spu_channel_current); +} + +static void +_player_meta_info_free(Emotion_Generic_Video *ev) +{ + eina_stringshare_replace(&ev->meta.title, NULL); + eina_stringshare_replace(&ev->meta.artist, NULL); + eina_stringshare_replace(&ev->meta.album, NULL); + eina_stringshare_replace(&ev->meta.year, NULL); + eina_stringshare_replace(&ev->meta.genre, NULL); + eina_stringshare_replace(&ev->meta.comment, NULL); + eina_stringshare_replace(&ev->meta.disc_id, NULL); + eina_stringshare_replace(&ev->meta.count, NULL); +} + +static void +_player_meta_info_read(Emotion_Generic_Video *ev) +{ + INF("Receiving meta info:"); + _player_meta_info_free(ev); + ev->meta.title = ev->cmd.param.meta.title; + ev->meta.artist = ev->cmd.param.meta.artist; + ev->meta.album = ev->cmd.param.meta.album; + ev->meta.year = ev->cmd.param.meta.year; + ev->meta.genre = ev->cmd.param.meta.genre; + ev->meta.comment = ev->cmd.param.meta.comment; + ev->meta.disc_id = ev->cmd.param.meta.disc_id; + ev->meta.count = ev->cmd.param.meta.count; + INF("title: '%s'", ev->meta.title); + INF("artist: '%s'", ev->meta.artist); + INF("album: '%s'", ev->meta.album); + INF("year: '%s'", ev->meta.year); + INF("genre: '%s'", ev->meta.genre); + INF("comment: '%s'", ev->meta.comment); + INF("disc_id: '%s'", ev->meta.disc_id); + INF("count: '%s'", ev->meta.count); +} + +static void +_player_file_closed(Emotion_Generic_Video *ev) +{ + INF("Closed previous file."); + eina_semaphore_free(&ev->shared->lock); + ev->closing = EINA_FALSE; + + if (ev->opening) + _file_open(ev); +} + +static void +_player_open_done(Emotion_Generic_Video *ev) +{ + int success; + + success = ev->cmd.param.i_num; + shm_unlink(ev->shmname); + + if (ev->file_changed) + { + _file_open(ev); + ev->file_changed = EINA_FALSE; + return; + } + + ev->opening = EINA_FALSE; + if (!success) + { + ERR("Could not open file."); + return; + } + + ev->file_ready = EINA_TRUE; + + _emotion_open_done(ev->obj); + + if (ev->play) + { + _player_send_cmd(ev, EM_CMD_PLAY); + _player_send_float(ev, ev->pos); + } + + _player_send_cmd(ev, EM_CMD_VOLUME_SET); + _player_send_float(ev, ev->volume); + + _player_send_cmd(ev, EM_CMD_SPEED_SET); + _player_send_float(ev, ev->speed); + + int mute = ev->audio_mute; + _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET); + _player_send_int(ev, mute); + + mute = ev->video_mute; + _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET); + _player_send_int(ev, mute); + + mute = ev->spu_mute; + _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET); + _player_send_int(ev, mute); + + INF("Open done"); +} + +static void +_player_cmd_process(Emotion_Generic_Video *ev) +{ + switch (ev->cmd.type) { + case EM_RESULT_INIT: + _player_ready(ev); + break; + case EM_RESULT_FRAME_NEW: + _player_new_frame(ev); + break; + case EM_RESULT_FILE_SET: + _player_file_set_done(ev); + break; + case EM_RESULT_FILE_SET_DONE: + _player_open_done(ev); + break; + case EM_RESULT_FILE_CLOSE: + _player_file_closed(ev); + break; + case EM_RESULT_PLAYBACK_STARTED: + _emotion_playback_started(ev->obj); + break; + case EM_RESULT_PLAYBACK_STOPPED: + ev->pos = 0; + _emotion_playback_finished(ev->obj); + _emotion_decode_stop(ev->obj); + + em_partial_shutdown(ev); + ev->player_restart = ecore_idler_add(_player_restart, ev); + break; + case EM_RESULT_FRAME_SIZE: + _player_frame_resize(ev); + break; + case EM_RESULT_LENGTH_CHANGED: + _player_length_changed(ev); + break; + case EM_RESULT_POSITION_CHANGED: + _player_position_changed(ev); + break; + case EM_RESULT_SEEKABLE_CHANGED: + _player_seekable_changed(ev); + break; + case EM_RESULT_AUDIO_TRACK_INFO: + _player_audio_tracks_info(ev); + break; + case EM_RESULT_VIDEO_TRACK_INFO: + _player_video_tracks_info(ev); + break; + case EM_RESULT_SPU_TRACK_INFO: + _player_spu_tracks_info(ev); + break; + case EM_RESULT_META_INFO: + _player_meta_info_read(ev); + break; + default: + WRN("received wrong command: %d", ev->cmd.type); + } + + ev->cmd.type = -1; +} + +static void +_player_cmd_single_int_process(Emotion_Generic_Video *ev) +{ + if (!_player_cmd_param_read(ev, &ev->cmd.param.i_num, sizeof(ev->cmd.param.i_num))) + return; + + _player_cmd_process(ev); +} + +static void +_player_cmd_single_float_process(Emotion_Generic_Video *ev) +{ + if (!_player_cmd_param_read(ev, &ev->cmd.param.f_num, sizeof(ev->cmd.param.f_num))) + return; + + _player_cmd_process(ev); +} + +static void +_player_cmd_double_int_process(Emotion_Generic_Video *ev) +{ + int param; + + if (ev->cmd.num_params == 0) + { + ev->cmd.num_params = 2; + ev->cmd.cur_param = 0; + ev->cmd.param.size.width = 0; + ev->cmd.param.size.height = 0; + } + + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + + if (ev->cmd.cur_param == 0) + ev->cmd.param.size.width = param; + else + ev->cmd.param.size.height = param; + + ev->cmd.cur_param++; + if (ev->cmd.cur_param == ev->cmd.num_params) + _player_cmd_process(ev); +} + +static void +_player_cmd_track_info(Emotion_Generic_Video *ev) +{ + int param; + int i; + + if (ev->cmd.num_params == 0) + { + ev->cmd.cur_param = 0; + ev->cmd.num_params = 2; + ev->cmd.param.track.channels = NULL; + ev->cmd.s_len = -1; + } + + while (ev->cmd.cur_param < 2) + { + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + + if (ev->cmd.cur_param == 0) + ev->cmd.param.track.current = param; + else + { + ev->cmd.param.track.total = param; + ev->cmd.num_params += param * 2; + ev->cmd.param.track.channels = + calloc(param, sizeof(*ev->cmd.param.track.channels)); + } + ev->cmd.cur_param++; + } + + if (ev->cmd.cur_param == ev->cmd.num_params) + { + _player_cmd_process(ev); + return; + } + + i = (ev->cmd.cur_param - 2) / 2; + if ((ev->cmd.cur_param % 2) == 0) // reading track id + { + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + ev->cmd.param.track.channels[i].id = param; + ev->cmd.cur_param++; + } + else // reading track name + { + char buf[PATH_MAX]; + + if (ev->cmd.s_len == -1) + { + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + ev->cmd.s_len = param; + } + + if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len)) + return; + ev->cmd.param.track.channels[i].name = + eina_stringshare_add_length(buf, ev->cmd.s_len); + ev->cmd.cur_param++; + ev->cmd.s_len = -1; + } + + if (ev->cmd.cur_param == ev->cmd.num_params) + _player_cmd_process(ev); +} + +static void +_player_cmd_meta_info(Emotion_Generic_Video *ev) +{ + int param; + const char *info; + char buf[PATH_MAX]; + + if (ev->cmd.num_params == 0) + { + ev->cmd.cur_param = 0; + ev->cmd.num_params = 8; + ev->cmd.param.meta.title = NULL; + ev->cmd.param.meta.artist = NULL; + ev->cmd.param.meta.album = NULL; + ev->cmd.param.meta.year = NULL; + ev->cmd.param.meta.genre = NULL; + ev->cmd.param.meta.comment = NULL; + ev->cmd.param.meta.disc_id = NULL; + ev->cmd.param.meta.count = NULL; + ev->cmd.s_len = -1; + } + + if (ev->cmd.s_len == -1) + { + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + ev->cmd.s_len = param; + } + + if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len)) + return; + + info = eina_stringshare_add_length(buf, ev->cmd.s_len); + ev->cmd.s_len = -1; + + if (ev->cmd.cur_param == 0) + ev->cmd.param.meta.title = info; + else if (ev->cmd.cur_param == 1) + ev->cmd.param.meta.artist = info; + else if (ev->cmd.cur_param == 2) + ev->cmd.param.meta.album = info; + else if (ev->cmd.cur_param == 3) + ev->cmd.param.meta.year = info; + else if (ev->cmd.cur_param == 4) + ev->cmd.param.meta.genre = info; + else if (ev->cmd.cur_param == 5) + ev->cmd.param.meta.comment = info; + else if (ev->cmd.cur_param == 6) + ev->cmd.param.meta.disc_id = info; + else if (ev->cmd.cur_param == 7) + ev->cmd.param.meta.count = info; + + ev->cmd.cur_param++; + + if (ev->cmd.cur_param == 8) + _player_cmd_process(ev); +} + +static void +_player_cmd_read(Emotion_Generic_Video *ev) +{ + if (ev->cmd.type < 0) + { + if (!_player_cmd_param_read(ev, &ev->cmd.type, sizeof(ev->cmd.type))) + return; + ev->cmd.num_params = 0; + } + + switch (ev->cmd.type) { + case EM_RESULT_INIT: + case EM_RESULT_FILE_SET: + case EM_RESULT_PLAYBACK_STARTED: + case EM_RESULT_PLAYBACK_STOPPED: + case EM_RESULT_FILE_CLOSE: + case EM_RESULT_FRAME_NEW: + _player_cmd_process(ev); + break; + case EM_RESULT_FILE_SET_DONE: + case EM_RESULT_SEEKABLE_CHANGED: + _player_cmd_single_int_process(ev); + break; + case EM_RESULT_LENGTH_CHANGED: + case EM_RESULT_POSITION_CHANGED: + _player_cmd_single_float_process(ev); + break; + case EM_RESULT_FRAME_SIZE: + _player_cmd_double_int_process(ev); + break; + case EM_RESULT_AUDIO_TRACK_INFO: + case EM_RESULT_VIDEO_TRACK_INFO: + case EM_RESULT_SPU_TRACK_INFO: + _player_cmd_track_info(ev); + break; + case EM_RESULT_META_INFO: + _player_cmd_meta_info(ev); + break; + + default: + WRN("received wrong command: %d", ev->cmd.type); + ev->cmd.type = -1; + } +} + +static Eina_Bool +_player_cmd_handler_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + Emotion_Generic_Video *ev = data; + + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) + { + ERR("an error occurred on fd_read %d.", ev->fd_read); + return ECORE_CALLBACK_CANCEL; + } + + _player_cmd_read(ev); + + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_player_data_cb(void *data, int type __UNUSED__, void *event) +{ + Ecore_Exe_Event_Data *ev = event; + Emotion_Generic_Video *evideo = data; + int i; + + if (ev->exe != evideo->player.exe) + { + INF("slave != ev->exe"); + return ECORE_CALLBACK_PASS_ON; + } + + for (i = 0; ev->lines[i].line; i++) + INF("received input from player: \"%s\"", ev->lines[i].line); + + return ECORE_CALLBACK_DONE; +} + +static Eina_Bool +_player_add_cb(void *data, int type __UNUSED__, void *event) +{ + Ecore_Exe_Event_Add *event_add = event; + Ecore_Exe *player = event_add->exe; + Emotion_Generic_Video *ev = data; + + if (ev->player.exe != player) + { + INF("ev->player != player."); + return ECORE_CALLBACK_PASS_ON; + } + + _player_send_cmd(ev, EM_CMD_INIT); + _player_send_str(ev, ev->shmname, EINA_TRUE); + + return ECORE_CALLBACK_DONE; +} + +static Eina_Bool +_player_del_cb(void *data, int type __UNUSED__, void *event __UNUSED__) +{ + Ecore_Exe_Event_Del *event_del = event; + Ecore_Exe *player = event_del->exe; + Emotion_Generic_Video *ev = data; + + if (ev->player.exe != player) + { + INF("ev->player != player."); + return ECORE_CALLBACK_PASS_ON; + } + + ERR("player died."); + + ev->player.exe = NULL; + ev->ready = EINA_FALSE; + ev->file_ready = EINA_FALSE; + ecore_main_fd_handler_del(ev->fd_handler); + close(ev->fd_read); + close(ev->fd_write); + ev->fd_read = -1; + ev->fd_write = -1; + _emotion_decode_stop(ev->obj); + + return ECORE_CALLBACK_DONE; +} + +static Eina_Bool +_player_exec(Emotion_Generic_Video *ev) +{ + int pipe_out[2]; + int pipe_in[2]; + char buf[PATH_MAX]; + + if (pipe(pipe_out) == -1) + { + ERR("could not create pipe for communication emotion -> player: %s", strerror(errno)); + return EINA_FALSE; + } + + if (pipe(pipe_in) == -1) + { + ERR("could not create pipe for communication player -> emotion: %s", strerror(errno)); + close(pipe_out[0]); + close(pipe_out[1]); + return EINA_FALSE; + } + + snprintf(buf, sizeof(buf), "%s %d %d\n", ev->cmdline, pipe_out[0], pipe_in[1]); + + ev->player.exe = ecore_exe_pipe_run( + buf, + ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE | + ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER, + ev); + + INF("created pipe emotion -> player: %d -> %d", pipe_out[1], pipe_out[0]); + INF("created pipe player -> emotion: %d -> %d", pipe_in[1], pipe_in[0]); + + close(pipe_in[1]); + close(pipe_out[0]); + + if (!ev->player.exe) + { + close(pipe_in[0]); + close(pipe_out[1]); + return EINA_FALSE; + } + + ev->fd_read = pipe_in[0]; + ev->fd_write = pipe_out[1]; + + ev->fd_handler = ecore_main_fd_handler_add( + ev->fd_read, ECORE_FD_READ | ECORE_FD_ERROR, _player_cmd_handler_cb, ev, + NULL, NULL); + + return EINA_TRUE; +} + +static Eina_Bool +_fork_and_exec(Emotion_Generic_Video *ev) +{ + char shmname[256]; + struct timeval tv; + + gettimeofday(&tv, NULL); + snprintf(shmname, sizeof(shmname), "/em-generic-shm_%d_%d", + (int)tv.tv_sec, (int)tv.tv_usec); + + ev->shmname = eina_stringshare_add(shmname); + + ev->player_add = ecore_event_handler_add( + ECORE_EXE_EVENT_ADD, _player_add_cb, ev); + ev->player_del = ecore_event_handler_add( + ECORE_EXE_EVENT_DEL, _player_del_cb, ev); + ev->player_data = ecore_event_handler_add( + ECORE_EXE_EVENT_DATA, _player_data_cb, ev); + + if (!_player_exec(ev)) + { + ERR("could not start player."); + return EINA_FALSE; + } + + ev->initializing = EINA_TRUE; + + return EINA_TRUE; +} + +static unsigned char +em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt) +{ + Emotion_Generic_Video *ev; + const char *player; + + if (!emotion_video) return 0; + player = _get_player(opt ? opt->player : NULL); + if (!player) return 0; + + ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev)); + if (!ev) return 0; + + ev->fd_read = -1; + ev->fd_write = -1; + ev->speed = 1.0; + ev->volume = 0.5; + ev->audio_mute = EINA_FALSE; + ev->cmd.type = -1; + + ev->obj = obj; + ev->cmdline = eina_stringshare_add(player); + *emotion_video = ev; + + return _fork_and_exec(ev); +} + +static void +em_partial_shutdown(Emotion_Generic_Video *ev) +{ + _emotion_image_reset(ev->obj); + + if (ev->player.exe) + { + ecore_exe_terminate(ev->player.exe); + ecore_exe_free(ev->player.exe); + ev->player.exe = NULL; + } + + if (ev->shared) + munmap(ev->shared, ev->shared->size); + ev->shared = NULL; + + if (ev->fd_read >= 0) + close(ev->fd_read); + ev->fd_read = -1; + if (ev->fd_write >= 0) + close(ev->fd_write); + ev->fd_write = -1; + if (ev->fd_handler) + ecore_main_fd_handler_del(ev->fd_handler); + ev->fd_handler = NULL; + + if (ev->player_add) ecore_event_handler_del(ev->player_add); + ev->player_add = NULL; + if (ev->player_data) ecore_event_handler_del(ev->player_data); + ev->player_data = NULL; + if (ev->player_del) ecore_event_handler_del(ev->player_del); + ev->player_del = NULL; + if (ev->player_restart) ecore_idler_del(ev->player_restart); + ev->player_restart = NULL; +} + +static int +em_shutdown(void *data) +{ + Emotion_Generic_Video *ev = data; + + if (!ev) return 0; + + eina_stringshare_del(ev->cmdline); + eina_stringshare_del(ev->shmname); + + em_partial_shutdown(ev); + + return 1; +} + +static unsigned char +em_file_open(const char *file, Evas_Object *obj __UNUSED__, void *data) +{ + Emotion_Generic_Video *ev = data; + INF("file set: %s", file); + if (!ev) return 0; + + eina_stringshare_replace(&ev->filename, file); + + ev->pos = 0; + ev->w = 0; + ev->h = 0; + ev->ratio = 1; + ev->len = 0; + + if (ev->ready && ev->opening) + { + INF("file changed while opening."); + ev->file_changed = EINA_TRUE; + return 1; + } + + ev->opening = EINA_TRUE; + + if (!ev->closing) + _file_open(ev); + + return 1; +} + +static void +em_file_close(void *data) +{ + Emotion_Generic_Video *ev = data; + + if (!ev || !ev->filename) return; + + INF("file close: %s", ev->filename); + + eina_stringshare_replace(&ev->filename, NULL); + + ev->file_ready = EINA_FALSE; + _audio_channels_free(ev); + _video_channels_free(ev); + _spu_channels_free(ev); + _player_meta_info_free(ev); + + if (ev->opening) + return; + + _player_send_cmd(ev, EM_CMD_FILE_CLOSE); + ev->closing = EINA_TRUE; +} + +static Emotion_Format +em_format_get(void *ef __UNUSED__) +{ + return EMOTION_FORMAT_BGRA; +} + +static void +em_video_data_size_get(void *data, int *w, int *h) +{ + Emotion_Generic_Video *ev = data; + + if (!ev) return; + if (w) *w = ev->w; + if (h) *h = ev->h; +} + +static void +em_play(void *data, double pos) +{ + Emotion_Generic_Video *ev = data; + + if (!ev) + return; + + ev->play = EINA_TRUE; + INF("play: %0.3f", pos); + + if (ev->initializing || ev->opening) + return; + + if (ev->ready) + { + _player_send_cmd(ev, EM_CMD_PLAY); + _player_send_float(ev, ev->pos); + return; + } + + if (!_player_exec(ev)) + ERR("could not start player."); +} + +static void +em_stop(void *data) +{ + Emotion_Generic_Video *ev = data; + + if (!ev) + return; + + ev->play = EINA_FALSE; + + if (!ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_STOP); + _emotion_decode_stop(ev->obj); +} + +static void +em_size_get(void *data, int *w, int *h) +{ + Emotion_Generic_Video *ev = data; + if (w) *w = ev->w; + if (h) *h = ev->h; +} + +static void +em_pos_set(void *data, double pos) +{ + Emotion_Generic_Video *ev = data; + float position = pos; + + if (!ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_POSITION_SET); + _player_send_float(ev, position); + _emotion_seek_done(ev->obj); +} + +static double +em_len_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->len; +} + +static double +em_buffer_size_get(void *data __UNUSED__) +{ + return 1.0; +} + +static int +em_fps_num_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return (int)(ev->fps * 1000.0); +} + +static int +em_fps_den_get(void *ef __UNUSED__) +{ + return 1000; +} + +static double +em_fps_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->fps; +} + +static double +em_pos_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->pos; +} + +static void +em_vis_set(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__) +{ +} + +static Emotion_Vis +em_vis_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->vis; +} + +static Eina_Bool +em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__) +{ + return EINA_FALSE; +} + +static double +em_ratio_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->ratio; +} + +static int em_video_handled(void *ef __UNUSED__) +{ + fprintf(stderr, "video handled!\n"); + return 1; +} + +static int em_audio_handled(void *ef __UNUSED__) +{ + fprintf(stderr, "audio handled!\n"); + return 1; +} + +static int em_seekable(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->seekable; +} + +static void em_frame_done(void *ef __UNUSED__) +{ +} + +static int +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__) +{ + return 0; +} + +static int +em_bgra_data_get(void *data, unsigned char **bgra_data) +{ + Emotion_Generic_Video *ev = data; + + if (!ev || !ev->file_ready) + return 0; + + // lock frame here + if (!eina_semaphore_lock(&ev->shared->lock)) + return 0; + + // send current frame to emotion + if (ev->shared->frame.emotion != ev->shared->frame.last) + { + ev->shared->frame.next = ev->shared->frame.emotion; + ev->shared->frame.emotion = ev->shared->frame.last; + } + *bgra_data = ev->frame.frames[ev->shared->frame.emotion]; + + if (ev->shared->frame_drop > 1) + WRN("dropped frames: %d", ev->shared->frame_drop - 1); + ev->shared->frame_drop = 0; + + // unlock frame here + eina_semaphore_release(&ev->shared->lock, 1); + ev->drop = 0; + + return 1; +} + +static void +em_event_feed(void *ef __UNUSED__, int event __UNUSED__) +{ +} + +static void +em_event_mouse_button_feed(void *ef __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__) +{ +} + +static void +em_event_mouse_move_feed(void *ef __UNUSED__, int x __UNUSED__, int y __UNUSED__) +{ +} + +static int +em_video_channel_count(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->video_channels_count; +} + +static void +em_video_channel_set(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->video_channels_count) + { + WRN("video channel out of range."); + return; + } + + _player_send_cmd(ev, EM_CMD_VIDEO_TRACK_SET); + _player_send_int(ev, ev->video_channels[channel].id); + ev->video_channel_current = channel; +} + +static int +em_video_channel_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->video_channel_current; +} + +static const char * +em_video_channel_name_get(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->video_channels_count) + { + WRN("video channel out of range."); + return NULL; + } + + return ev->video_channels[channel].name; +} + +static void +em_video_channel_mute_set(void *data, int mute) +{ + Emotion_Generic_Video *ev = data; + + ev->video_mute = !!mute; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET); + _player_send_int(ev, mute); +} + +static int +em_video_channel_mute_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->video_mute; +} + +static int +em_audio_channel_count(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->audio_channels_count; +} + +static void +em_audio_channel_set(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->audio_channels_count) + { + WRN("audio channel out of range."); + return; + } + + _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET); + _player_send_int(ev, ev->audio_channels[channel].id); + ev->audio_channel_current = channel; +} + +static int +em_audio_channel_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->audio_channel_current; +} + +static const char * +em_audio_channel_name_get(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->audio_channels_count) + { + WRN("audio channel out of range."); + return NULL; + } + + return ev->audio_channels[channel].name; +} + +static void +em_audio_channel_mute_set(void *data, int mute) +{ + Emotion_Generic_Video *ev = data; + + ev->audio_mute = !!mute; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET); + _player_send_int(ev, mute); +} + +static int +em_audio_channel_mute_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->audio_mute; +} + +static void +em_audio_channel_volume_set(void *data, double vol) +{ + Emotion_Generic_Video *ev = data; + + if (vol > 1.0) vol = 1.0; + if (vol < 0.0) vol = 0.0; + + ev->volume = vol; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_VOLUME_SET); + _player_send_float(ev, ev->volume); +} + +static double +em_audio_channel_volume_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->volume; +} + +static int +em_spu_channel_count(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->spu_channels_count; +} + +static void +em_spu_channel_set(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->spu_channels_count) + { + WRN("spu channel out of range."); + return; + } + + _player_send_cmd(ev, EM_CMD_SPU_TRACK_SET); + _player_send_int(ev, ev->spu_channels[channel].id); + ev->spu_channel_current = channel; +} + +static int +em_spu_channel_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->spu_channel_current; +} + +static const char * +em_spu_channel_name_get(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->spu_channels_count) + { + WRN("spu channel out of range."); + return NULL; + } + + return ev->spu_channels[channel].name; +} + +static void +em_spu_channel_mute_set(void *data, int mute) +{ + Emotion_Generic_Video *ev = data; + + ev->spu_mute = !!mute; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET); + _player_send_int(ev, mute); +} + +static int +em_spu_channel_mute_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->spu_mute; +} + +static int +em_chapter_count(void *ef __UNUSED__) +{ + int num = 0; + return num; +} + +static void +em_chapter_set(void *ef __UNUSED__, int chapter __UNUSED__) +{ +} + +static int +em_chapter_get(void *ef __UNUSED__) +{ + int num = 0; + return num; +} + +static const char * +em_chapter_name_get(void *ef __UNUSED__, int chapter __UNUSED__) +{ + return NULL; +} + +static void +em_speed_set(void *data, double speed) +{ + Emotion_Generic_Video *ev = data; + float rate = speed; + ev->speed = rate; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_SPEED_SET); + _player_send_float(ev, rate); +} + +static double +em_speed_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return (double)ev->speed; +} + +static int +em_eject(void *ef __UNUSED__) +{ + return 1; +} + +static const char * +em_meta_get(void *data, int meta) +{ + Emotion_Generic_Video *ev = data; + + switch (meta) { + case EMOTION_META_INFO_TRACK_TITLE: + return ev->meta.title; + case EMOTION_META_INFO_TRACK_ARTIST: + return ev->meta.artist; + case EMOTION_META_INFO_TRACK_ALBUM: + return ev->meta.album; + case EMOTION_META_INFO_TRACK_YEAR: + return ev->meta.year; + case EMOTION_META_INFO_TRACK_GENRE: + return ev->meta.genre; + case EMOTION_META_INFO_TRACK_COMMENT: + return ev->meta.comment; + case EMOTION_META_INFO_TRACK_DISC_ID: + return ev->meta.disc_id; + case EMOTION_META_INFO_TRACK_COUNT: + return ev->meta.count; + } + + return NULL; +} + +static Emotion_Video_Module em_module = +{ + em_init, /* init */ + em_shutdown, /* shutdown */ + em_file_open, /* file_open */ + em_file_close, /* file_close */ + em_play, /* play */ + em_stop, /* stop */ + em_size_get, /* size_get */ + em_pos_set, /* pos_set */ + em_len_get, /* len_get */ + em_buffer_size_get, /* buffer_size_get */ + em_fps_num_get, /* fps_num_get */ + em_fps_den_get, /* fps_den_get */ + em_fps_get, /* fps_get */ + em_pos_get, /* pos_get */ + em_vis_set, /* vis_set */ + em_vis_get, /* vis_get */ + em_vis_supported, /* vis_supported */ + em_ratio_get, /* ratio_get */ + em_video_handled, /* video_handled */ + em_audio_handled, /* audio_handled */ + em_seekable, /* seekable */ + em_frame_done, /* frame_done */ + em_format_get, /* format_get */ + em_video_data_size_get, /* video_data_size_get */ + em_yuv_rows_get, /* yuv_rows_get */ + em_bgra_data_get, /* bgra_data_get */ + em_event_feed, /* event_feed */ + em_event_mouse_button_feed, /* event_mouse_button_feed */ + em_event_mouse_move_feed, /* event_mouse_move_feed */ + em_video_channel_count, /* video_channel_count */ + em_video_channel_set, /* video_channel_set */ + em_video_channel_get, /* video_channel_get */ + em_video_channel_name_get, /* video_channel_name_get */ + em_video_channel_mute_set, /* video_channel_mute_set */ + em_video_channel_mute_get, /* video_channel_mute_get */ + em_audio_channel_count, /* audio_channel_count */ + em_audio_channel_set, /* audio_channel_set */ + em_audio_channel_get, /* audio_channel_get */ + em_audio_channel_name_get, /* audio_channel_name_get */ + em_audio_channel_mute_set, /* audio_channel_mute_set */ + em_audio_channel_mute_get, /* audio_channel_mute_get */ + em_audio_channel_volume_set, /* audio_channel_volume_set */ + em_audio_channel_volume_get, /* audio_channel_volume_get */ + em_spu_channel_count, /* spu_channel_count */ + em_spu_channel_set, /* spu_channel_set */ + em_spu_channel_get, /* spu_channel_get */ + em_spu_channel_name_get, /* spu_channel_name_get */ + em_spu_channel_mute_set, /* spu_channel_mute_set */ + em_spu_channel_mute_get, /* spu_channel_mute_get */ + em_chapter_count, /* chapter_count */ + em_chapter_set, /* chapter_set */ + em_chapter_get, /* chapter_get */ + em_chapter_name_get, /* chapter_name_get */ + em_speed_set, /* speed_set */ + em_speed_get, /* speed_get */ + em_eject, /* eject */ + em_meta_get, /* meta_get */ + NULL, /* priority_set */ + NULL, /* priority_get */ + NULL /* handle */ +}; + +static Eina_Bool +module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt) +{ + if (!module) { + return EINA_FALSE; + } + + if (_emotion_generic_log_domain < 0) + { + eina_threads_init(); + eina_log_threads_enable(); + _emotion_generic_log_domain = eina_log_domain_register + ("emotion-generic", EINA_COLOR_LIGHTCYAN); + if (_emotion_generic_log_domain < 0) + { + EINA_LOG_CRIT("Could not register log domain 'emotion-generic'"); + return EINA_FALSE; + } + } + + + if (!em_module.init(obj, video, opt)) { + return EINA_FALSE; + } + + *module = &em_module; + + return EINA_TRUE; +} + +static void module_close(Emotion_Video_Module *module __UNUSED__, void *video) +{ + em_module.shutdown(video); +} + + +Eina_Bool +generic_module_init(void) +{ + if (!pfx) + { + pfx = eina_prefix_new(NULL, emotion_object_add, + "EMOTION", "emotion", NULL, + PACKAGE_BIN_DIR, + PACKAGE_LIB_DIR, + PACKAGE_DATA_DIR, + ""); + if (!pfx) return EINA_FALSE; + } + return _emotion_module_register("generic", module_open, module_close); +} + +static void +generic_module_shutdown(void) +{ + if (pfx) + { + eina_prefix_free(pfx); + pfx = NULL; + } + _emotion_module_unregister("generic"); +} + +#ifndef EMOTION_STATIC_BUILD_GENERIC + +EINA_MODULE_INIT(generic_module_init); +EINA_MODULE_SHUTDOWN(generic_module_shutdown); + +#endif + diff --git a/src/modules/generic/emotion_generic.h b/src/modules/generic/emotion_generic.h new file mode 100644 index 0000000..ed3bdb0 --- /dev/null +++ b/src/modules/generic/emotion_generic.h @@ -0,0 +1,112 @@ +#ifndef EMOTION_GENERIC_H +#define EMOTION_GENERIC_H + +#include "Emotion_Generic_Plugin.h" + +/* default values */ + +typedef struct _Emotion_Generic_Video Emotion_Generic_Video; +typedef struct _Emotion_Generic_Player Emotion_Generic_Player; +typedef struct _Emotion_Generic_Cmd_Buffer Emotion_Generic_Cmd_Buffer; +typedef struct _Emotion_Generic_Channel Emotion_Generic_Channel; +typedef struct _Emotion_Generic_Meta Emotion_Generic_Meta; + +struct _Emotion_Generic_Player +{ + Ecore_Exe *exe; +}; + +struct _Emotion_Generic_Channel +{ + int id; + const char *name; +}; + +struct _Emotion_Generic_Meta +{ + const char *title; + const char *artist; + const char *album; + const char *year; + const char *genre; + const char *comment; + const char *disc_id; + const char *count; +}; + +struct _Emotion_Generic_Cmd_Buffer +{ + char *tmp; + int type; + ssize_t i, total; + int s_len; + int num_params, cur_param; + int padding; + union { + struct { + int width; + int height; + } size; + int i_num; + float f_num; + struct { + int total; + int current; + Emotion_Generic_Channel *channels; + } track; + Emotion_Generic_Meta meta; + } param; +}; + +/* emotion/generic main structure */ +struct _Emotion_Generic_Video +{ + const char *cmdline; + const char *shmname; + + Emotion_Generic_Player player; + Emotion_Generic_Cmd_Buffer cmd; + Ecore_Event_Handler *player_add, *player_del, *player_data; + Ecore_Idler *player_restart; + int drop; + int fd_read, fd_write; + Ecore_Fd_Handler *fd_handler; + + const char *filename; + volatile double len; + volatile double pos; + double fps; + double ratio; + int w, h; + Evas_Object *obj; + Emotion_Generic_Video_Shared *shared; + Emotion_Generic_Video_Frame frame; + volatile int fq; + float volume; + float speed; + Emotion_Vis vis; + Eina_Bool initializing : 1; + Eina_Bool ready : 1; + Eina_Bool play : 1; + Eina_Bool video_mute : 1; + Eina_Bool audio_mute : 1; + Eina_Bool spu_mute : 1; + Eina_Bool seekable : 1; + volatile Eina_Bool opening : 1; + volatile Eina_Bool closing : 1; + Eina_Bool file_changed : 1; + Eina_Bool file_ready : 1; + int audio_channels_count; + int audio_channel_current; + Emotion_Generic_Channel *audio_channels; + int video_channels_count; + int video_channel_current; + Emotion_Generic_Channel *video_channels; + int spu_channels_count; + int spu_channel_current; + Emotion_Generic_Channel *spu_channels; + Emotion_Generic_Meta meta; +}; + +#endif + diff --git a/src/modules/gstreamer/Makefile.am b/src/modules/gstreamer/Makefile.am new file mode 100644 index 0000000..3672510 --- /dev/null +++ b/src/modules/gstreamer/Makefile.am @@ -0,0 +1,37 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EMOTION_CFLAGS@ \ +@EMOTION_CPPFLAGS@ \ +@EFL_EMOTION_BUILD@ \ +@GSTREAMER_CFLAGS@ \ +@GSTREAMER_INTERFACE_CFLAGS@ \ +@ECORE_X_CFLAGS@ + +if EMOTION_BUILD_GSTREAMER +if !EMOTION_STATIC_BUILD_GSTREAMER + +pkgdir = $(libdir)/emotion + +pkg_LTLIBRARIES = gstreamer.la +gstreamer_la_SOURCES = \ +emotion_gstreamer.c \ +emotion_sink.c \ +emotion_alloc.c \ +emotion_fakeeos.c \ +emotion_convert.c + +gstreamer_la_LIBADD = @EMOTION_LIBS@ @ECORE_X_LIBS@ @GSTREAMER_LIBS@ @GSTREAMER_INTERFACE_LIBS@ $(top_builddir)/src/lib/libemotion.la +gstreamer_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +gstreamer_la_LIBTOOLFLAGS = --tag=disable-static +gstreamer_la_DEPENDENCIES = $(top_builddir)/config.h + +endif +endif + +EXTRA_DIST = emotion_gstreamer.h diff --git a/src/modules/gstreamer/emotion_alloc.c b/src/modules/gstreamer/emotion_alloc.c new file mode 100644 index 0000000..05062bd --- /dev/null +++ b/src/modules/gstreamer/emotion_alloc.c @@ -0,0 +1,91 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + +#include "Emotion.h" +#include "emotion_gstreamer.h" + +Emotion_Gstreamer_Buffer * +emotion_gstreamer_buffer_alloc(EvasVideoSinkPrivate *sink, + GstBuffer *buffer, + Eina_Bool preroll) +{ + Emotion_Gstreamer_Buffer *send; + + if (!sink->ev) return NULL; + + send = malloc(sizeof (Emotion_Gstreamer_Buffer)); + if (!send) return NULL; + + send->sink = sink; + send->frame = gst_buffer_ref(buffer); + send->preroll = preroll; + send->force = EINA_FALSE; + sink->ev->out++; + send->ev = sink->ev; + + return send; +} + +void +emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send) +{ + send->ev->in++; + + if (send->ev->in == send->ev->out + && send->ev->threads == NULL + && send->ev->delete_me) + em_shutdown(send->ev); + + gst_buffer_unref(send->frame); + free(send); +} + +Emotion_Gstreamer_Message * +emotion_gstreamer_message_alloc(Emotion_Gstreamer_Video *ev, + GstMessage *msg) +{ + Emotion_Gstreamer_Message *send; + + if (!ev) return NULL; + + send = malloc(sizeof (Emotion_Gstreamer_Message)); + if (!send) return NULL; + + ev->out++; + send->ev = ev; + send->msg = gst_message_ref(msg); + + return send; +} + +void +emotion_gstreamer_message_free(Emotion_Gstreamer_Message *send) +{ + send->ev->in++; + + if (send->ev->in == send->ev->out + && send->ev->threads == NULL + && send->ev->delete_me) + em_shutdown(send->ev); + + gst_message_unref(send->msg); + free(send); +} diff --git a/src/modules/gstreamer/emotion_convert.c b/src/modules/gstreamer/emotion_convert.c new file mode 100644 index 0000000..3d3b46e --- /dev/null +++ b/src/modules/gstreamer/emotion_convert.c @@ -0,0 +1,252 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + +#include "Emotion.h" +#include "emotion_gstreamer.h" + +static inline void +_evas_video_bgrx_step(unsigned char *evas_data, const unsigned char *gst_data, + unsigned int w, unsigned int h __UNUSED__, unsigned int output_height, unsigned int step) +{ + unsigned int x; + unsigned int y; + + for (y = 0; y < output_height; ++y) + { + for (x = 0; x < w; x++) + { + evas_data[0] = gst_data[0]; + evas_data[1] = gst_data[1]; + evas_data[2] = gst_data[2]; + evas_data[3] = 255; + gst_data += step; + evas_data += 4; + } + } +} + +static void +_evas_video_bgr(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +{ + _evas_video_bgrx_step(evas_data, gst_data, w, h, output_height, 3); +} + +static void +_evas_video_bgrx(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +{ + _evas_video_bgrx_step(evas_data, gst_data, w, h, output_height, 4); +} + +static void +_evas_video_bgra(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h __UNUSED__, unsigned int output_height) +{ + unsigned int x; + unsigned int y; + + for (y = 0; y < output_height; ++y) + { + unsigned char alpha; + + for (x = 0; x < w; ++x) + { + alpha = gst_data[3]; + evas_data[0] = (gst_data[0] * alpha) / 255; + evas_data[1] = (gst_data[1] * alpha) / 255; + evas_data[2] = (gst_data[2] * alpha) / 255; + evas_data[3] = alpha; + gst_data += 4; + evas_data += 4; + } + } +} + +static void +_evas_video_i420(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +{ + const unsigned char **rows; + unsigned int i, j; + unsigned int rh; + unsigned int stride_y, stride_uv; + + rh = output_height; + + rows = (const unsigned char **)evas_data; + + stride_y = GST_ROUND_UP_4(w); + stride_uv = GST_ROUND_UP_8(w) / 2; + + for (i = 0; i < rh; i++) + rows[i] = &gst_data[i * stride_y]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[h * stride_y + j * stride_uv]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[h * stride_y + + (rh / 2) * stride_uv + + j * stride_uv]; +} + +static void +_evas_video_yv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +{ + const unsigned char **rows; + unsigned int i, j; + unsigned int rh; + unsigned int stride_y, stride_uv; + + rh = output_height; + + rows = (const unsigned char **)evas_data; + + stride_y = GST_ROUND_UP_4(w); + stride_uv = GST_ROUND_UP_8(w) / 2; + + for (i = 0; i < rh; i++) + rows[i] = &gst_data[i * stride_y]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[h * stride_y + + (rh / 2) * stride_uv + + j * stride_uv]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[h * stride_y + j * stride_uv]; +} + +static void +_evas_video_yuy2(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h __UNUSED__, unsigned int output_height) +{ + const unsigned char **rows; + unsigned int i; + unsigned int stride; + + rows = (const unsigned char **)evas_data; + + stride = GST_ROUND_UP_4(w * 2); + + for (i = 0; i < output_height; i++) + rows[i] = &gst_data[i * stride]; +} + +static void +_evas_video_nv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h __UNUSED__, unsigned int output_height) +{ + const unsigned char **rows; + unsigned int i, j; + unsigned int rh; + + rh = output_height; + + rows = (const unsigned char **)evas_data; + + for (i = 0; i < rh; i++) + rows[i] = &gst_data[i * w]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[rh * w + j * w]; +} + +static void +_evas_video_mt12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height __UNUSED__) +{ + const unsigned char **rows; + unsigned int i; + unsigned int j; + + rows = (const unsigned char **)evas_data; + + for (i = 0; i < (h / 32) / 2; i++) + rows[i] = &gst_data[i * w * 2 * 32]; + + if ((h / 32) % 2) + { + rows[i] = &gst_data[i * w * 2 * 32]; + i++; + } + + for (j = 0; j < ((h / 2) / 32) / 2; ++j, ++i) + rows[i] = &gst_data[h * w + j * (w / 2) * 2 * 16]; +} + +void +_evas_video_st12_multiplane(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height __UNUSED__) +{ + const GstMultiPlaneImageBuffer *mp_buf = (const GstMultiPlaneImageBuffer *) gst_data; + const unsigned char **rows; + unsigned int i; + unsigned int j; + + rows = (const unsigned char **)evas_data; + + for (i = 0; i < (h / 32) / 2; i++) + rows[i] = mp_buf->uaddr[0] + i * w * 2 * 32; + if ((h / 32) % 2) + { + rows[i] = mp_buf->uaddr[0] + i * w * 2 * 32; + i++; + } + + for (j = 0; j < ((h / 2) / 16) / 2; j++, i++) + { + rows[i] = mp_buf->uaddr[1] + j * w * 2 * 16 * 2; + } + if (((h / 2) / 16) % 2) + rows[i] = mp_buf->uaddr[1] + j * w * 2 * 16 * 2; +} + +void +_evas_video_st12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w __UNUSED__, unsigned int h, unsigned int output_height __UNUSED__) +{ + const SCMN_IMGB *imgb = (const SCMN_IMGB *) gst_data; + const unsigned char **rows; + unsigned int i, j; + + rows = (const unsigned char **)evas_data; + + for (i = 0; i < (h / 32) / 2; i++) + rows[i] = imgb->uaddr[0] + i * imgb->stride[0] * 2 * 32; + if ((h / 32) % 2) + { + rows[i] = imgb->uaddr[0] + i * imgb->stride[0] * 2 * 32; + i++; + } + + for (j = 0; j < (unsigned int) imgb->elevation[1] / 32 / 2; j++, i++) + rows[i] = imgb->uaddr[1] + j * imgb->stride[1] * 32 * 2; + if ((imgb->elevation[1] / 32) % 2) + rows[i++] = imgb->uaddr[1] + j * imgb->stride[1] * 32 * 2; +} + +const ColorSpace_FourCC_Convertion colorspace_fourcc_convertion[] = { + { "I420", GST_MAKE_FOURCC('I', '4', '2', '0'), EVAS_COLORSPACE_YCBCR422P601_PL, _evas_video_i420, EINA_TRUE }, + { "YV12", GST_MAKE_FOURCC('Y', 'V', '1', '2'), EVAS_COLORSPACE_YCBCR422P601_PL, _evas_video_yv12, EINA_TRUE }, + { "YUY2", GST_MAKE_FOURCC('Y', 'U', 'Y', '2'), EVAS_COLORSPACE_YCBCR422601_PL, _evas_video_yuy2, EINA_FALSE }, + { "NV12", GST_MAKE_FOURCC('N', 'V', '1', '2'), EVAS_COLORSPACE_YCBCR420NV12601_PL, _evas_video_nv12, EINA_TRUE }, + { "TM12", GST_MAKE_FOURCC('T', 'M', '1', '2'), EVAS_COLORSPACE_YCBCR420TM12601_PL, _evas_video_mt12, EINA_TRUE }, + { NULL, 0, 0, NULL, 0 } +}; + +const ColorSpace_Format_Convertion colorspace_format_convertion[] = { + { "BGR", GST_VIDEO_FORMAT_BGR, EVAS_COLORSPACE_ARGB8888, _evas_video_bgr }, + { "BGRx", GST_VIDEO_FORMAT_BGRx, EVAS_COLORSPACE_ARGB8888, _evas_video_bgrx }, + { "BGRA", GST_VIDEO_FORMAT_BGRA, EVAS_COLORSPACE_ARGB8888, _evas_video_bgra }, + { NULL, 0, 0, NULL } +}; diff --git a/src/modules/gstreamer/emotion_fakeeos.c b/src/modules/gstreamer/emotion_fakeeos.c new file mode 100644 index 0000000..a9e1bbe --- /dev/null +++ b/src/modules/gstreamer/emotion_fakeeos.c @@ -0,0 +1,71 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + +#include "Emotion.h" +#include "emotion_gstreamer.h" + +typedef struct _FakeEOSBin +{ + GstBin parent; +} FakeEOSBin; + +typedef struct _FakeEOSBinClass +{ + GstBinClass parent; +} FakeEOSBinClass; + +GST_BOILERPLATE(FakeEOSBin, fakeeos_bin, GstBin, + GST_TYPE_BIN); + +static void +fakeeos_bin_handle_message(GstBin * bin, GstMessage * message) +{ + /* FakeEOSBin *fakeeos = (FakeEOSBin *)(bin); */ + + switch (GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_EOS: + /* what to do here ? just returning at the moment */ + return ; + default: + break; + } + + GST_BIN_CLASS(parent_class)->handle_message(bin, message); +} + +static void +fakeeos_bin_base_init(gpointer g_class __UNUSED__) +{ +} + +static void +fakeeos_bin_class_init(FakeEOSBinClass * klass) +{ + GstBinClass *gstbin_class = GST_BIN_CLASS(klass); + + gstbin_class->handle_message = + GST_DEBUG_FUNCPTR (fakeeos_bin_handle_message); +} + +static void +fakeeos_bin_init(FakeEOSBin *src __UNUSED__, + FakeEOSBinClass *klass __UNUSED__) +{ +} diff --git a/src/modules/gstreamer/emotion_gstreamer.c b/src/modules/gstreamer/emotion_gstreamer.c new file mode 100644 index 0000000..df29de8 --- /dev/null +++ b/src/modules/gstreamer/emotion_gstreamer.c @@ -0,0 +1,2130 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#include +#include +#include + +#define HTTP_STREAM 0 +#define RTSP_STREAM 1 +#include +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + +#include "Emotion.h" +#include "emotion_private.h" +#include "emotion_gstreamer.h" + +Eina_Bool window_manager_video = EINA_FALSE; +int _emotion_gstreamer_log_domain = -1; +Eina_Bool debug_fps = EINA_FALSE; +Eina_Bool _ecore_x_available = EINA_FALSE; + +static Ecore_Idler *restart_idler; + +/* Callbacks to get the eos */ +static void _for_each_tag (GstTagList const* list, gchar const* tag, void *data); +static void _free_metadata (Emotion_Gstreamer_Metadata *m); + +/* Interface */ + +static unsigned char em_init (Evas_Object *obj, + void **emotion_video, + Emotion_Module_Options *opt); + +static unsigned char em_file_open (const char *file, + Evas_Object *obj, + void *video); + +static void em_file_close (void *video); + +static void em_play (void *video, + double pos); + +static void em_stop (void *video); + +static void em_size_get (void *video, + int *width, + int *height); + +static void em_pos_set (void *video, + double pos); + + +static double em_len_get (void *video); + +static double em_buffer_size_get (void *video); + +static int em_fps_num_get (void *video); + +static int em_fps_den_get (void *video); + +static double em_fps_get (void *video); + +static double em_pos_get (void *video); + +static void em_vis_set (void *video, + Emotion_Vis vis); + +static Emotion_Vis em_vis_get (void *video); + +static Eina_Bool em_vis_supported (void *video, + Emotion_Vis vis); + +static double em_ratio_get (void *video); + +static int em_video_handled (void *video); + +static int em_audio_handled (void *video); + +static int em_seekable (void *video); + +static void em_frame_done (void *video); + +static Emotion_Format em_format_get (void *video); + +static void em_video_data_size_get (void *video, + int *w, + int *h); + +static int em_yuv_rows_get (void *video, + int w, + int h, + unsigned char **yrows, + unsigned char **urows, + unsigned char **vrows); + +static int em_bgra_data_get (void *video, + unsigned char **bgra_data); + +static void em_event_feed (void *video, + int event); + +static void em_event_mouse_button_feed (void *video, + int button, + int x, + int y); + +static void em_event_mouse_move_feed (void *video, + int x, + int y); + +static int em_video_channel_count (void *video); + +static void em_video_channel_set (void *video, + int channel); + +static int em_video_channel_get (void *video); + +static const char *em_video_channel_name_get (void *video, + int channel); + +static void em_video_channel_mute_set (void *video, + int mute); + +static int em_video_channel_mute_get (void *video); + +static int em_audio_channel_count (void *video); + +static void em_audio_channel_set (void *video, + int channel); + +static int em_audio_channel_get (void *video); + +static const char *em_audio_channel_name_get (void *video, + int channel); + +static void em_audio_channel_mute_set (void *video, + int mute); + +static int em_audio_channel_mute_get (void *video); + +static void em_audio_channel_volume_set (void *video, + double vol); + +static double em_audio_channel_volume_get (void *video); + +static int em_spu_channel_count (void *video); + +static void em_spu_channel_set (void *video, + int channel); + +static int em_spu_channel_get (void *video); + +static const char *em_spu_channel_name_get (void *video, + int channel); + +static void em_spu_channel_mute_set (void *video, + int mute); + +static int em_spu_channel_mute_get (void *video); + +static int em_chapter_count (void *video); + +static void em_chapter_set (void *video, + int chapter); + +static int em_chapter_get (void *video); + +static const char *em_chapter_name_get (void *video, + int chapter); + +static void em_speed_set (void *video, + double speed); + +static double em_speed_get (void *video); + +static int em_eject (void *video); + +static const char *em_meta_get (void *video, + int meta); + +static void em_priority_set (void *video, + Eina_Bool pri); +static Eina_Bool em_priority_get (void *video); + +static GstBusSyncReply _eos_sync_fct(GstBus *bus, + GstMessage *message, + gpointer data); + +static Eina_Bool _em_restart_stream(void *data); + +/* Module interface */ + +static Emotion_Video_Module em_module = +{ + em_init, /* init */ + em_shutdown, /* shutdown */ + em_file_open, /* file_open */ + em_file_close, /* file_close */ + em_play, /* play */ + em_stop, /* stop */ + em_size_get, /* size_get */ + em_pos_set, /* pos_set */ + em_len_get, /* len_get */ + em_buffer_size_get, /* buffer_size_get */ + em_fps_num_get, /* fps_num_get */ + em_fps_den_get, /* fps_den_get */ + em_fps_get, /* fps_get */ + em_pos_get, /* pos_get */ + em_vis_set, /* vis_set */ + em_vis_get, /* vis_get */ + em_vis_supported, /* vis_supported */ + em_ratio_get, /* ratio_get */ + em_video_handled, /* video_handled */ + em_audio_handled, /* audio_handled */ + em_seekable, /* seekable */ + em_frame_done, /* frame_done */ + em_format_get, /* format_get */ + em_video_data_size_get, /* video_data_size_get */ + em_yuv_rows_get, /* yuv_rows_get */ + em_bgra_data_get, /* bgra_data_get */ + em_event_feed, /* event_feed */ + em_event_mouse_button_feed, /* event_mouse_button_feed */ + em_event_mouse_move_feed, /* event_mouse_move_feed */ + em_video_channel_count, /* video_channel_count */ + em_video_channel_set, /* video_channel_set */ + em_video_channel_get, /* video_channel_get */ + em_video_channel_name_get, /* video_channel_name_get */ + em_video_channel_mute_set, /* video_channel_mute_set */ + em_video_channel_mute_get, /* video_channel_mute_get */ + em_audio_channel_count, /* audio_channel_count */ + em_audio_channel_set, /* audio_channel_set */ + em_audio_channel_get, /* audio_channel_get */ + em_audio_channel_name_get, /* audio_channel_name_get */ + em_audio_channel_mute_set, /* audio_channel_mute_set */ + em_audio_channel_mute_get, /* audio_channel_mute_get */ + em_audio_channel_volume_set, /* audio_channel_volume_set */ + em_audio_channel_volume_get, /* audio_channel_volume_get */ + em_spu_channel_count, /* spu_channel_count */ + em_spu_channel_set, /* spu_channel_set */ + em_spu_channel_get, /* spu_channel_get */ + em_spu_channel_name_get, /* spu_channel_name_get */ + em_spu_channel_mute_set, /* spu_channel_mute_set */ + em_spu_channel_mute_get, /* spu_channel_mute_get */ + em_chapter_count, /* chapter_count */ + em_chapter_set, /* chapter_set */ + em_chapter_get, /* chapter_get */ + em_chapter_name_get, /* chapter_name_get */ + em_speed_set, /* speed_set */ + em_speed_get, /* speed_get */ + em_eject, /* eject */ + em_meta_get, /* meta_get */ + em_priority_set, /* priority_set */ + em_priority_get, /* priority_get */ + NULL /* handle */ +}; + +static int priority_overide = 0; + +static Emotion_Video_Stream * +emotion_video_stream_new(Emotion_Gstreamer_Video *ev) +{ + Emotion_Video_Stream *vstream; + + if (!ev) return NULL; + + vstream = (Emotion_Video_Stream *)calloc(1, sizeof(Emotion_Video_Stream)); + if (!vstream) return NULL; + + ev->video_streams = eina_list_append(ev->video_streams, vstream); + if (eina_error_get()) + { + free(vstream); + return NULL; + } + return vstream; +} + +static const char * +emotion_visualization_element_name_get(Emotion_Vis visualisation) +{ + switch (visualisation) + { + case EMOTION_VIS_NONE: + return NULL; + case EMOTION_VIS_GOOM: + return "goom"; + case EMOTION_VIS_LIBVISUAL_BUMPSCOPE: + return "libvisual_bumpscope"; + case EMOTION_VIS_LIBVISUAL_CORONA: + return "libvisual_corona"; + case EMOTION_VIS_LIBVISUAL_DANCING_PARTICLES: + return "libvisual_dancingparticles"; + case EMOTION_VIS_LIBVISUAL_GDKPIXBUF: + return "libvisual_gdkpixbuf"; + case EMOTION_VIS_LIBVISUAL_G_FORCE: + return "libvisual_G-Force"; + case EMOTION_VIS_LIBVISUAL_GOOM: + return "libvisual_goom"; + case EMOTION_VIS_LIBVISUAL_INFINITE: + return "libvisual_infinite"; + case EMOTION_VIS_LIBVISUAL_JAKDAW: + return "libvisual_jakdaw"; + case EMOTION_VIS_LIBVISUAL_JESS: + return "libvisual_jess"; + case EMOTION_VIS_LIBVISUAL_LV_ANALYSER: + return "libvisual_lv_analyzer"; + case EMOTION_VIS_LIBVISUAL_LV_FLOWER: + return "libvisual_lv_flower"; + case EMOTION_VIS_LIBVISUAL_LV_GLTEST: + return "libvisual_lv_gltest"; + case EMOTION_VIS_LIBVISUAL_LV_SCOPE: + return "libvisual_lv_scope"; + case EMOTION_VIS_LIBVISUAL_MADSPIN: + return "libvisual_madspin"; + case EMOTION_VIS_LIBVISUAL_NEBULUS: + return "libvisual_nebulus"; + case EMOTION_VIS_LIBVISUAL_OINKSIE: + return "libvisual_oinksie"; + case EMOTION_VIS_LIBVISUAL_PLASMA: + return "libvisual_plazma"; + default: + return "goom"; + } +} + +static unsigned char +em_init(Evas_Object *obj, + void **emotion_video, + Emotion_Module_Options *opt __UNUSED__) +{ + Emotion_Gstreamer_Video *ev; + GError *error; + + if (!emotion_video) + return 0; + + ev = calloc(1, sizeof(Emotion_Gstreamer_Video)); + if (!ev) return 0; + + ev->obj = obj; + + /* Initialization of gstreamer */ + if (!gst_init_check(NULL, NULL, &error)) + goto failure; + + /* Default values */ + ev->ratio = 1.0; + ev->vis = EMOTION_VIS_NONE; + ev->volume = 0.8; + ev->play_started = 0; + ev->delete_me = EINA_FALSE; + ev->threads = NULL; + + *emotion_video = ev; + + return 1; + +failure: + free(ev); + + return 0; +} + +static void +em_cleanup(Emotion_Gstreamer_Video *ev) +{ + Emotion_Audio_Stream *astream; + Emotion_Video_Stream *vstream; + + if (ev->send) + { + emotion_gstreamer_buffer_free(ev->send); + ev->send = NULL; + } + + if (ev->eos_bus) + { + gst_object_unref(GST_OBJECT(ev->eos_bus)); + ev->eos_bus = NULL; + } + + if (ev->metadata) + { + _free_metadata(ev->metadata); + ev->metadata = NULL; + } + + if (ev->last_buffer) + { + gst_buffer_unref(ev->last_buffer); + ev->last_buffer = NULL; + } + + if (!ev->stream) + { + evas_object_image_video_surface_set(emotion_object_image_get(ev->obj), NULL); + ev->stream = EINA_TRUE; + } + + if (ev->pipeline) + { + gstreamer_video_sink_new(ev, ev->obj, NULL); + + g_object_set(G_OBJECT(ev->esink), "ev", NULL, NULL); + g_object_set(G_OBJECT(ev->esink), "evas-object", NULL, NULL); + gst_element_set_state(ev->pipeline, GST_STATE_NULL); + gst_object_unref(ev->pipeline); + + ev->pipeline = NULL; + ev->sink = NULL; + + if (ev->eteepad) gst_object_unref(ev->eteepad); + ev->eteepad = NULL; + if (ev->xvteepad) gst_object_unref(ev->xvteepad); + ev->xvteepad = NULL; + if (ev->xvpad) gst_object_unref(ev->xvpad); + ev->xvpad = NULL; + + ev->src_width = 0; + ev->src_height = 0; + +#ifdef HAVE_ECORE_X + fprintf(stderr, "destroying window: %i\n", ev->win); + if (ev->win) ecore_x_window_free(ev->win); + ev->win = 0; +#endif + } + + if (restart_idler) + { + ecore_idler_del(restart_idler); + restart_idler = NULL; + } + + EINA_LIST_FREE(ev->audio_streams, astream) + free(astream); + EINA_LIST_FREE(ev->video_streams, vstream) + free(vstream); +} + +int +em_shutdown(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + if (!ev) + return 0; + + if (ev->threads) + { + Ecore_Thread *t; + + EINA_LIST_FREE(ev->threads, t) + ecore_thread_cancel(t); + + ev->delete_me = EINA_TRUE; + return EINA_FALSE; + } + + if (ev->in != ev->out) + { + ev->delete_me = EINA_TRUE; + return EINA_FALSE; + } + + em_cleanup(ev); + + free(ev); + + return 1; +} + + +static unsigned char +em_file_open(const char *file, + Evas_Object *obj, + void *video) +{ + Emotion_Gstreamer_Video *ev; + Eina_Strbuf *sbuf = NULL; + const char *uri; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!file) return EINA_FALSE; + if (strstr(file, "://") == NULL) + { + sbuf = eina_strbuf_new(); + eina_strbuf_append(sbuf, "file://"); + if (strncmp(file, "./", 2) == 0) + file += 2; + if (strstr(file, ":/") != NULL) + { /* We absolutely need file:///C:/ under Windows, so adding it here */ + eina_strbuf_append(sbuf, "/"); + } + else if (*file != '/') + { + char tmp[PATH_MAX]; + + if (getcwd(tmp, PATH_MAX)) + { + eina_strbuf_append(sbuf, tmp); + eina_strbuf_append(sbuf, "/"); + } + } + eina_strbuf_append(sbuf, file); + } + + ev->play_started = 0; + ev->pipeline_parsed = 0; + + uri = sbuf ? eina_strbuf_string_get(sbuf) : file; + DBG("setting file to '%s'", uri); + ev->pipeline = gstreamer_video_sink_new(ev, obj, uri); + if (sbuf) eina_strbuf_free(sbuf); + + if (!ev->pipeline) + return EINA_FALSE; + + ev->eos_bus = gst_pipeline_get_bus(GST_PIPELINE(ev->pipeline)); + if (!ev->eos_bus) + { + ERR("could not get the bus"); + return EINA_FALSE; + } + + gst_bus_set_sync_handler(ev->eos_bus, _eos_sync_fct, ev); + + /* Evas Object */ + ev->obj = obj; + + ev->position = 0.0; + + return 1; +} + +static void +em_file_close(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + if (!ev) + return; + + if (ev->threads) + { + Ecore_Thread *t; + + EINA_LIST_FREE(ev->threads, t) + ecore_thread_cancel(t); + } + + em_cleanup(ev); + + ev->pipeline_parsed = EINA_FALSE; + ev->play_started = 0; +} + +static void +em_play(void *video, + double pos __UNUSED__) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + if (!ev->pipeline) return ; + + if (ev->pipeline_parsed) + gst_element_set_state(ev->pipeline, GST_STATE_PLAYING); + ev->play = 1; + ev->play_started = 1; +} + +static void +em_stop(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!ev->pipeline) return ; + + if (ev->pipeline_parsed) + gst_element_set_state(ev->pipeline, GST_STATE_PAUSED); + ev->play = 0; +} + +static void +em_size_get(void *video, + int *width, + int *height) +{ + Emotion_Gstreamer_Video *ev; + Emotion_Video_Stream *vstream; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE)) + goto on_error; + + vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1); + if (vstream) + { + if (width) *width = vstream->width; + if (height) *height = vstream->height; + + return ; + } + + on_error: + if (width) *width = 0; + if (height) *height = 0; +} + +static void +em_pos_set(void *video, + double pos) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!ev->pipeline) return ; + + if (ev->play) + gst_element_set_state(ev->pipeline, GST_STATE_PAUSED); + + gst_element_seek(ev->pipeline, 1.0, + GST_FORMAT_TIME, + GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, + (gint64)(pos * (double)GST_SECOND), + GST_SEEK_TYPE_NONE, -1); + + if (ev->play) + gst_element_set_state(ev->pipeline, GST_STATE_PLAYING); +} + +static double +em_len_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + Emotion_Video_Stream *vstream; + Emotion_Audio_Stream *astream; + Eina_List *l; + GstFormat fmt; + gint64 val; + gboolean ret; + + ev = video; + fmt = GST_FORMAT_TIME; + + if (!ev->pipeline) return 0.0; + + ret = gst_element_query_duration(ev->pipeline, &fmt, &val); + if (!ret) + goto fallback; + + if (fmt != GST_FORMAT_TIME) + { + DBG("requrested duration in time, but got %s instead.", + gst_format_get_name(fmt)); + goto fallback; + } + + if (val <= 0.0) + goto fallback; + + return val / 1000000000.0; + + fallback: + if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE)) + return 0.0; + + EINA_LIST_FOREACH(ev->audio_streams, l, astream) + if (astream->length_time >= 0) + return astream->length_time; + + EINA_LIST_FOREACH(ev->video_streams, l, vstream) + if (vstream->length_time >= 0) + return vstream->length_time; + + return 0.0; +} + +static double +em_buffer_size_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + + GstQuery *query; + gboolean busy; + gint percent; + + ev = video; + + if (!ev->pipeline) return 0.0; + + query = gst_query_new_buffering(GST_FORMAT_DEFAULT); + if (gst_element_query(ev->pipeline, query)) + gst_query_parse_buffering_percent(query, &busy, &percent); + else + percent = 100; + + gst_query_unref(query); + return ((float)(percent)) / 100.0; +} + +static int +em_fps_num_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + Emotion_Video_Stream *vstream; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE)) + return 0; + + vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1); + if (vstream) + return vstream->fps_num; + + return 0; +} + +static int +em_fps_den_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + Emotion_Video_Stream *vstream; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE)) + return 1; + + vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1); + if (vstream) + return vstream->fps_den; + + return 1; +} + +static double +em_fps_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + Emotion_Video_Stream *vstream; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE)) + return 0.0; + + vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1); + if (vstream) + return (double)vstream->fps_num / (double)vstream->fps_den; + + return 0.0; +} + +static double +em_pos_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + GstFormat fmt; + gint64 val; + gboolean ret; + + ev = video; + fmt = GST_FORMAT_TIME; + + if (!ev->pipeline) return 0.0; + + ret = gst_element_query_position(ev->pipeline, &fmt, &val); + if (!ret) + return ev->position; + + if (fmt != GST_FORMAT_TIME) + { + ERR("requrested position in time, but got %s instead.", + gst_format_get_name(fmt)); + return ev->position; + } + + ev->position = val / 1000000000.0; + return ev->position; +} + +static void +em_vis_set(void *video, + Emotion_Vis vis) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + ev->vis = vis; +} + +static Emotion_Vis +em_vis_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + return ev->vis; +} + +static Eina_Bool +em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis) +{ + const char *name; + GstElementFactory *factory; + + if (vis == EMOTION_VIS_NONE) + return EINA_TRUE; + + name = emotion_visualization_element_name_get(vis); + if (!name) + return EINA_FALSE; + + factory = gst_element_factory_find(name); + if (!factory) + return EINA_FALSE; + + gst_object_unref(factory); + return EINA_TRUE; +} + +static double +em_ratio_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + return ev->ratio; +} + +static int +em_video_handled(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE); + + if (!eina_list_count(ev->video_streams)) + return 0; + + return 1; +} + +static int +em_audio_handled(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE); + + if (!eina_list_count(ev->audio_streams)) + return 0; + + return 1; +} + +static int +em_seekable(void *video __UNUSED__) +{ + return 1; +} + +static void +em_frame_done(void *video __UNUSED__) +{ +} + +static Emotion_Format +em_format_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + Emotion_Video_Stream *vstream; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE)) + return EMOTION_FORMAT_NONE; + + vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1); + if (vstream) + { + switch (vstream->fourcc) + { + case GST_MAKE_FOURCC('I', '4', '2', '0'): + return EMOTION_FORMAT_I420; + case GST_MAKE_FOURCC('Y', 'V', '1', '2'): + return EMOTION_FORMAT_YV12; + case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'): + return EMOTION_FORMAT_YUY2; + case GST_MAKE_FOURCC('A', 'R', 'G', 'B'): + return EMOTION_FORMAT_BGRA; + default: + return EMOTION_FORMAT_NONE; + } + } + return EMOTION_FORMAT_NONE; +} + +static void +em_video_data_size_get(void *video, int *w, int *h) +{ + Emotion_Gstreamer_Video *ev; + Emotion_Video_Stream *vstream; + + ev = (Emotion_Gstreamer_Video *)video; + + if (ev->pipeline && (!ev->video_stream_nbr || !ev->video_streams)) + if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE)) + goto on_error; + + vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1); + if (vstream) + { + *w = vstream->width; + *h = vstream->height; + + return ; + } + + on_error: + *w = 0; + *h = 0; +} + +static int +em_yuv_rows_get(void *video __UNUSED__, + int w __UNUSED__, + int h __UNUSED__, + unsigned char **yrows __UNUSED__, + unsigned char **urows __UNUSED__, + unsigned char **vrows __UNUSED__) +{ + return 0; +} + +static int +em_bgra_data_get(void *video __UNUSED__, unsigned char **bgra_data __UNUSED__) +{ + return 0; +} + +static void +em_event_feed(void *video __UNUSED__, int event __UNUSED__) +{ +} + +static void +em_event_mouse_button_feed(void *video __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__) +{ +} + +static void +em_event_mouse_move_feed(void *video __UNUSED__, int x __UNUSED__, int y __UNUSED__) +{ +} + +/* Video channels */ +static int +em_video_channel_count(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE); + + return eina_list_count(ev->video_streams); +} + +static void +em_video_channel_set(void *video __UNUSED__, + int channel __UNUSED__) +{ +#if 0 + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + if (channel < 0) channel = 0; +#endif + /* FIXME: a faire... */ +} + +static int +em_video_channel_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE); + + return ev->video_stream_nbr; +} + +static const char * +em_video_channel_name_get(void *video __UNUSED__, + int channel __UNUSED__) +{ + return NULL; +} + +static void +em_video_channel_mute_set(void *video, + int mute) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + ev->video_mute = mute; +} + +static int +em_video_channel_mute_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + return ev->video_mute; +} + +/* Audio channels */ + +static int +em_audio_channel_count(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE); + + return eina_list_count(ev->audio_streams); +} + +static void +em_audio_channel_set(void *video __UNUSED__, + int channel __UNUSED__) +{ +#if 0 + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + if (channel < -1) channel = -1; +#endif + /* FIXME: a faire... */ +} + +static int +em_audio_channel_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE); + + return ev->audio_stream_nbr; +} + +static const char * +em_audio_channel_name_get(void *video __UNUSED__, + int channel __UNUSED__) +{ + return NULL; +} + +#define GST_PLAY_FLAG_AUDIO (1 << 1) + +static void +em_audio_channel_mute_set(void *video, + int mute) +{ + /* NOTE: at first I wanted to completly shutdown the audio path on mute, + but that's not possible as the audio sink could be the clock source + for the pipeline (at least that's the case on some of the hardware + I have been tested emotion on. + */ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!ev->pipeline) return ; + + ev->audio_mute = mute; + + g_object_set(G_OBJECT(ev->pipeline), "mute", !!mute, NULL); +} + +static int +em_audio_channel_mute_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + return ev->audio_mute; +} + +static void +em_audio_channel_volume_set(void *video, + double vol) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!ev->pipeline) return ; + + if (vol < 0.0) + vol = 0.0; + if (vol > 1.0) + vol = 1.0; + ev->volume = vol; + g_object_set(G_OBJECT(ev->pipeline), "volume", vol, NULL); +} + +static double +em_audio_channel_volume_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = (Emotion_Gstreamer_Video *)video; + + return ev->volume; +} + +/* spu stuff */ + +static int +em_spu_channel_count(void *video __UNUSED__) +{ + return 0; +} + +static void +em_spu_channel_set(void *video __UNUSED__, int channel __UNUSED__) +{ +} + +static int +em_spu_channel_get(void *video __UNUSED__) +{ + return 1; +} + +static const char * +em_spu_channel_name_get(void *video __UNUSED__, int channel __UNUSED__) +{ + return NULL; +} + +static void +em_spu_channel_mute_set(void *video __UNUSED__, int mute __UNUSED__) +{ +} + +static int +em_spu_channel_mute_get(void *video __UNUSED__) +{ + return 0; +} + +static int +em_chapter_count(void *video __UNUSED__) +{ + return 0; +} + +static void +em_chapter_set(void *video __UNUSED__, int chapter __UNUSED__) +{ +} + +static int +em_chapter_get(void *video __UNUSED__) +{ + return 0; +} + +static const char * +em_chapter_name_get(void *video __UNUSED__, int chapter __UNUSED__) +{ + return NULL; +} + +static void +em_speed_set(void *video __UNUSED__, double speed __UNUSED__) +{ +} + +static double +em_speed_get(void *video __UNUSED__) +{ + return 1.0; +} + +static int +em_eject(void *video __UNUSED__) +{ + return 1; +} + +static const char * +em_meta_get(void *video, int meta) +{ + Emotion_Gstreamer_Video *ev; + const char *str = NULL; + + ev = (Emotion_Gstreamer_Video *)video; + + if (!ev || !ev->metadata) return NULL; + switch (meta) + { + case META_TRACK_TITLE: + str = ev->metadata->title; + break; + case META_TRACK_ARTIST: + str = ev->metadata->artist; + break; + case META_TRACK_ALBUM: + str = ev->metadata->album; + break; + case META_TRACK_YEAR: + str = ev->metadata->year; + break; + case META_TRACK_GENRE: + str = ev->metadata->genre; + break; + case META_TRACK_COMMENT: + str = ev->metadata->comment; + break; + case META_TRACK_DISCID: + str = ev->metadata->disc_id; + break; + default: + break; + } + + return str; +} + +static void +em_priority_set(void *video, Eina_Bool pri) +{ + Emotion_Gstreamer_Video *ev; + + ev = video; + if (priority_overide > 3) return ; /* If we failed to much to create that pipeline, let's don't wast our time anymore */ + + if (ev->priority != pri && ev->pipeline) + { + if (ev->threads) + { + Ecore_Thread *t; + + EINA_LIST_FREE(ev->threads, t) + ecore_thread_cancel(t); + } + em_cleanup(ev); + restart_idler = ecore_idler_add(_em_restart_stream, ev); + } + ev->priority = pri; +} + +static Eina_Bool +em_priority_get(void *video) +{ + Emotion_Gstreamer_Video *ev; + + ev = video; + return !ev->stream; +} + +#ifdef HAVE_ECORE_X +static Eina_Bool +_ecore_event_x_destroy(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__) +{ + Ecore_X_Event_Window_Destroy *ev = event; + + fprintf(stderr, "killed window: %x (%x)\n", ev->win, ev->event_win); + + return EINA_TRUE; +} +#endif + +static Eina_Bool +module_open(Evas_Object *obj, + const Emotion_Video_Module **module, + void **video, + Emotion_Module_Options *opt) +{ +#ifdef HAVE_ECORE_X + Ecore_X_Window *roots; + int num; +#endif + + if (!module) + return EINA_FALSE; + + if (_emotion_gstreamer_log_domain < 0) + { + eina_threads_init(); + eina_log_threads_enable(); + _emotion_gstreamer_log_domain = eina_log_domain_register + ("emotion-gstreamer", EINA_COLOR_LIGHTCYAN); + if (_emotion_gstreamer_log_domain < 0) + { + EINA_LOG_CRIT("Could not register log domain 'emotion-gstreamer'"); + return EINA_FALSE; + } + } + + if (!em_module.init(obj, video, opt)) + return EINA_FALSE; + +#ifdef HAVE_ECORE_X + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _ecore_event_x_destroy, NULL); +#endif + + if (getenv("EMOTION_FPS_DEBUG")) debug_fps = EINA_TRUE; + + eina_threads_init(); + +#ifdef HAVE_ECORE_X + if (ecore_x_init(NULL) > 0) + { + _ecore_x_available = EINA_TRUE; + } + + /* Check if the window manager is able to handle our special Xv window. */ + roots = _ecore_x_available ? ecore_x_window_root_list(&num) : NULL; + if (roots && num > 0) + { + Ecore_X_Window win, twin; + int nwins; + + nwins = ecore_x_window_prop_window_get(roots[0], + ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, + &win, 1); + if (nwins > 0) + { + nwins = ecore_x_window_prop_window_get(win, + ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, + &twin, 1); + if (nwins > 0 && twin == win) + { + Ecore_X_Atom *supported; + int supported_num; + int i; + + if (ecore_x_netwm_supported_get(roots[0], &supported, &supported_num)) + { + Eina_Bool parent = EINA_FALSE; + Eina_Bool video_position = EINA_FALSE; + + for (i = 0; i < supported_num; ++i) + { + if (supported[i] == ECORE_X_ATOM_E_VIDEO_PARENT) + parent = EINA_TRUE; + else if (supported[i] == ECORE_X_ATOM_E_VIDEO_POSITION) + video_position = EINA_TRUE; + if (parent && video_position) + break; + } + + if (parent && video_position) + { + window_manager_video = EINA_TRUE; + } + } + } + } + } + free(roots); +#endif + + *module = &em_module; + return EINA_TRUE; +} + +static void +module_close(Emotion_Video_Module *module __UNUSED__, + void *video) +{ + em_module.shutdown(video); + +#ifdef HAVE_ECORE_X + if (_ecore_x_available) + { + ecore_x_shutdown(); + } +#endif + + eina_threads_shutdown(); +} + +Eina_Bool +gstreamer_module_init(void) +{ + GError *error; + + if (!gst_init_check(0, NULL, &error)) + { + EINA_LOG_CRIT("Could not init GStreamer"); + return EINA_FALSE; + } + + if (gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR, + "emotion-sink", + "video sink plugin for Emotion", + gstreamer_plugin_init, + VERSION, + "LGPL", + "Enlightenment", + PACKAGE, + "http://www.enlightenment.org/") == FALSE) + { + EINA_LOG_CRIT("Could not load static gstreamer video sink for Emotion."); + return EINA_FALSE; + } + + return _emotion_module_register("gstreamer", module_open, module_close); +} + +void +gstreamer_module_shutdown(void) +{ + _emotion_module_unregister("gstreamer"); + + gst_deinit(); +} + +#ifndef EMOTION_STATIC_BUILD_GSTREAMER + +EINA_MODULE_INIT(gstreamer_module_init); +EINA_MODULE_SHUTDOWN(gstreamer_module_shutdown); + +#endif + +static void +_for_each_tag(GstTagList const* list, + gchar const* tag, + void *data) +{ + Emotion_Gstreamer_Video *ev; + int i; + int count; + + + ev = (Emotion_Gstreamer_Video*)data; + + if (!ev || !ev->metadata) return; + + count = gst_tag_list_get_tag_size(list, tag); + + for (i = 0; i < count; i++) + { + if (!strcmp(tag, GST_TAG_TITLE)) + { + char *str; + g_free(ev->metadata->title); + if (gst_tag_list_get_string(list, GST_TAG_TITLE, &str)) + ev->metadata->title = str; + else + ev->metadata->title = NULL; + break; + } + if (!strcmp(tag, GST_TAG_ALBUM)) + { + gchar *str; + g_free(ev->metadata->album); + if (gst_tag_list_get_string(list, GST_TAG_ALBUM, &str)) + ev->metadata->album = str; + else + ev->metadata->album = NULL; + break; + } + if (!strcmp(tag, GST_TAG_ARTIST)) + { + gchar *str; + g_free(ev->metadata->artist); + if (gst_tag_list_get_string(list, GST_TAG_ARTIST, &str)) + ev->metadata->artist = str; + else + ev->metadata->artist = NULL; + break; + } + if (!strcmp(tag, GST_TAG_GENRE)) + { + gchar *str; + g_free(ev->metadata->genre); + if (gst_tag_list_get_string(list, GST_TAG_GENRE, &str)) + ev->metadata->genre = str; + else + ev->metadata->genre = NULL; + break; + } + if (!strcmp(tag, GST_TAG_COMMENT)) + { + gchar *str; + g_free(ev->metadata->comment); + if (gst_tag_list_get_string(list, GST_TAG_COMMENT, &str)) + ev->metadata->comment = str; + else + ev->metadata->comment = NULL; + break; + } + if (!strcmp(tag, GST_TAG_DATE)) + { + gchar *str; + const GValue *date; + g_free(ev->metadata->year); + date = gst_tag_list_get_value_index(list, GST_TAG_DATE, 0); + if (date) + str = g_strdup_value_contents(date); + else + str = NULL; + ev->metadata->year = str; + break; + } + + if (!strcmp(tag, GST_TAG_TRACK_NUMBER)) + { + gchar *str; + const GValue *track; + g_free(ev->metadata->count); + track = gst_tag_list_get_value_index(list, GST_TAG_TRACK_NUMBER, 0); + if (track) + str = g_strdup_value_contents(track); + else + str = NULL; + ev->metadata->count = str; + break; + } + +#ifdef GST_TAG_CDDA_CDDB_DISCID + if (!strcmp(tag, GST_TAG_CDDA_CDDB_DISCID)) + { + gchar *str; + const GValue *discid; + g_free(ev->metadata->disc_id); + discid = gst_tag_list_get_value_index(list, GST_TAG_CDDA_CDDB_DISCID, 0); + if (discid) + str = g_strdup_value_contents(discid); + else + str = NULL; + ev->metadata->disc_id = str; + break; + } +#endif + } + +} + +static void +_free_metadata(Emotion_Gstreamer_Metadata *m) +{ + if (!m) return; + + g_free(m->title); + g_free(m->album); + g_free(m->artist); + g_free(m->genre); + g_free(m->comment); + g_free(m->year); + g_free(m->count); + g_free(m->disc_id); + + free(m); +} + +static Eina_Bool +_em_restart_stream(void *data) +{ + Emotion_Gstreamer_Video *ev; + + ev = data; + + ev->pipeline = gstreamer_video_sink_new(ev, ev->obj, ev->uri); + + if (ev->pipeline) + { + ev->eos_bus = gst_pipeline_get_bus(GST_PIPELINE(ev->pipeline)); + if (!ev->eos_bus) + { + ERR("could not get the bus"); + return EINA_FALSE; + } + + gst_bus_set_sync_handler(ev->eos_bus, _eos_sync_fct, ev); + } + + restart_idler = NULL; + + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool +_video_size_get(GstElement *elem, int *width, int *height) +{ + GstIterator *itr = NULL; + GstCaps *caps; + GstStructure *str; + gpointer pad; + Eina_Bool ret = EINA_FALSE; + + itr = gst_element_iterate_src_pads(elem); + while(gst_iterator_next(itr, &pad) && !ret) + { + caps = gst_pad_get_caps(GST_PAD(pad)); + str = gst_caps_get_structure(caps, 0); + if (g_strrstr(gst_structure_get_name(str), "video")) + { + if (gst_structure_get_int(str, "width", width) && gst_structure_get_int(str, "height", height)) + ret = EINA_TRUE; + } + gst_caps_unref(caps); + gst_object_unref(pad); + } + gst_iterator_free(itr); + + return ret; +} + +static void +_no_more_pads(GstElement *decodebin, gpointer data) +{ + GstIterator *itr = NULL; + gpointer elem; + Emotion_Gstreamer_Video *ev = data; + + itr = gst_bin_iterate_elements(GST_BIN(decodebin)); + while(gst_iterator_next(itr, &elem)) + { + if(_video_size_get(GST_ELEMENT(elem), &ev->src_width, &ev->src_height)) + { + double ratio; + + ratio = (double)ev->src_width / (double)ev->src_height; + _emotion_frame_resize(ev->obj, ev->src_width, ev->src_height, ratio); + + gst_object_unref(elem); + break; + } + gst_object_unref(elem); + } + gst_iterator_free(itr); +} + +static void +_eos_main_fct(void *data) +{ + Emotion_Gstreamer_Message *send; + Emotion_Gstreamer_Video *ev; + GstMessage *msg; + + send = data; + ev = send->ev; + msg = send->msg; + + if (ev->play_started && !ev->delete_me) + { + _emotion_playback_started(ev->obj); + ev->play_started = 0; + } + + switch (GST_MESSAGE_TYPE(msg)) + { + case GST_MESSAGE_EOS: + if (!ev->delete_me) + { + ev->play = 0; + _emotion_decode_stop(ev->obj); + _emotion_playback_finished(ev->obj); + } + break; + case GST_MESSAGE_TAG: + if (!ev->delete_me) + { + GstTagList *new_tags; + gst_message_parse_tag(msg, &new_tags); + if (new_tags) + { + gst_tag_list_foreach(new_tags, + (GstTagForeachFunc)_for_each_tag, + ev); + gst_tag_list_free(new_tags); + } + } + break; + case GST_MESSAGE_ASYNC_DONE: + if (!ev->delete_me) _emotion_seek_done(ev->obj); + break; + case GST_MESSAGE_STREAM_STATUS: + break; + case GST_MESSAGE_STATE_CHANGED: + if (!ev->delete_me) + { + if (!g_signal_handlers_disconnect_by_func(msg->src, _no_more_pads, ev)) + g_signal_connect(msg->src, "no-more-pads", G_CALLBACK(_no_more_pads), ev); + } + break; + case GST_MESSAGE_ERROR: + em_cleanup(ev); + + if (ev->priority) + { + ERR("Switching back to canvas rendering."); + ev->priority = EINA_FALSE; + priority_overide++; + + restart_idler = ecore_idler_add(_em_restart_stream, ev); + } + break; + default: + ERR("bus say: %s [%i - %s]", + GST_MESSAGE_SRC_NAME(msg), + GST_MESSAGE_TYPE(msg), + GST_MESSAGE_TYPE_NAME(msg)); + break; + } + + emotion_gstreamer_message_free(send); +} + +static GstBusSyncReply +_eos_sync_fct(GstBus *bus __UNUSED__, GstMessage *msg, gpointer data) +{ + Emotion_Gstreamer_Video *ev = data; + Emotion_Gstreamer_Message *send; + + switch (GST_MESSAGE_TYPE(msg)) + { + case GST_MESSAGE_EOS: + case GST_MESSAGE_TAG: + case GST_MESSAGE_ASYNC_DONE: + case GST_MESSAGE_STREAM_STATUS: + INF("bus say: %s [%i - %s]", + GST_MESSAGE_SRC_NAME(msg), + GST_MESSAGE_TYPE(msg), + GST_MESSAGE_TYPE_NAME(msg)); + send = emotion_gstreamer_message_alloc(ev, msg); + + if (send) ecore_main_loop_thread_safe_call_async(_eos_main_fct, send); + + break; + + case GST_MESSAGE_STATE_CHANGED: + { + GstState old_state, new_state; + + gst_message_parse_state_changed(msg, &old_state, &new_state, NULL); + INF("Element %s changed state from %s to %s.", + GST_OBJECT_NAME(msg->src), + gst_element_state_get_name(old_state), + gst_element_state_get_name(new_state)); + + if (!strncmp(GST_OBJECT_NAME(msg->src), "decodebin", 9) && !strcmp(gst_element_state_get_name(new_state), "READY")) + { + send = emotion_gstreamer_message_alloc(ev, msg); + + if (send) ecore_main_loop_thread_safe_call_async(_eos_main_fct, send); + } + break; + } + case GST_MESSAGE_ERROR: + { + GError *error; + gchar *debug; + + gst_message_parse_error(msg, &error, &debug); + ERR("ERROR from element %s: %s", GST_OBJECT_NAME(msg->src), error->message); + ERR("Debugging info: %s", (debug) ? debug : "none"); + g_error_free(error); + g_free(debug); + + if (strncmp(GST_OBJECT_NAME(msg->src), "xvimagesink", 11) == 0) + { + send = emotion_gstreamer_message_alloc(ev, msg); + + if (send) ecore_main_loop_thread_safe_call_async(_eos_main_fct, send); + } + break; + } + case GST_MESSAGE_WARNING: + { + GError *error; + gchar *debug; + + gst_message_parse_warning(msg, &error, &debug); + WRN("WARNING from element %s: %s", GST_OBJECT_NAME(msg->src), error->message); + WRN("Debugging info: %s", (debug) ? debug : "none"); + g_error_free(error); + g_free(debug); + break; + } + default: + WRN("bus say: %s [%i - %s]", + GST_MESSAGE_SRC_NAME(msg), + GST_MESSAGE_TYPE(msg), + GST_MESSAGE_TYPE_NAME(msg)); + break; + } + + gst_message_unref(msg); + + return GST_BUS_DROP; +} + +Eina_Bool +_emotion_gstreamer_video_pipeline_parse(Emotion_Gstreamer_Video *ev, + Eina_Bool force) +{ + gboolean res; + int i; + + if (ev->pipeline_parsed) + return EINA_TRUE; + + if (force && ev->threads) + { + Ecore_Thread *t; + + EINA_LIST_FREE(ev->threads, t) + ecore_thread_cancel(t); + } + + if (ev->threads) + return EINA_FALSE; + + res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + if (res == GST_STATE_CHANGE_NO_PREROLL) + { + gst_element_set_state(ev->pipeline, GST_STATE_PLAYING); + + res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + } + + /** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */ + /** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */ + if (getenv("EMOTION_GSTREAMER_DOT")) + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline), + GST_DEBUG_GRAPH_SHOW_ALL, + getenv("EMOTION_GSTREAMER_DOT")); + + if (!(res == GST_STATE_CHANGE_SUCCESS + || res == GST_STATE_CHANGE_NO_PREROLL)) + { + ERR("Unable to get GST_CLOCK_TIME_NONE."); + return EINA_FALSE; + } + + g_object_get(G_OBJECT(ev->pipeline), + "n-audio", &ev->audio_stream_nbr, + "n-video", &ev->video_stream_nbr, + NULL); + + if ((ev->video_stream_nbr == 0) && (ev->audio_stream_nbr == 0)) + { + ERR("No audio nor video stream found"); + return EINA_FALSE; + } + + /* video stream */ + for (i = 0; i < ev->video_stream_nbr; i++) + { + Emotion_Video_Stream *vstream; + GstPad *pad = NULL; + GstCaps *caps; + GstStructure *structure; + GstQuery *query; + const GValue *val; + gchar *str; + + gdouble length_time = 0.0; + gint width; + gint height; + gint fps_num; + gint fps_den; + guint32 fourcc = 0; + + g_signal_emit_by_name(ev->pipeline, "get-video-pad", i, &pad); + if (!pad) + continue; + + caps = gst_pad_get_negotiated_caps(pad); + if (!caps) + goto unref_pad_v; + structure = gst_caps_get_structure(caps, 0); + str = gst_caps_to_string(caps); + + if (!gst_structure_get_int(structure, "width", &width)) + goto unref_caps_v; + if (!gst_structure_get_int(structure, "height", &height)) + goto unref_caps_v; + if (!gst_structure_get_fraction(structure, "framerate", &fps_num, &fps_den)) + goto unref_caps_v; + + if (g_str_has_prefix(str, "video/x-raw-yuv")) + { + val = gst_structure_get_value(structure, "format"); + fourcc = gst_value_get_fourcc(val); + } + else if (g_str_has_prefix(str, "video/x-raw-rgb")) + fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B'); + else + goto unref_caps_v; + + query = gst_query_new_duration(GST_FORMAT_TIME); + if (gst_pad_peer_query(pad, query)) + { + gint64 t; + + gst_query_parse_duration(query, NULL, &t); + length_time = (double)t / (double)GST_SECOND; + } + else + goto unref_query_v; + + vstream = emotion_video_stream_new(ev); + if (!vstream) goto unref_query_v; + + vstream->length_time = length_time; + vstream->width = width; + vstream->height = height; + vstream->fps_num = fps_num; + vstream->fps_den = fps_den; + vstream->fourcc = fourcc; + vstream->index = i; + + unref_query_v: + gst_query_unref(query); + unref_caps_v: + gst_caps_unref(caps); + unref_pad_v: + gst_object_unref(pad); + } + + /* Audio streams */ + for (i = 0; i < ev->audio_stream_nbr; i++) + { + Emotion_Audio_Stream *astream; + GstPad *pad; + GstCaps *caps; + GstStructure *structure; + GstQuery *query; + + gdouble length_time = 0.0; + gint channels; + gint samplerate; + + g_signal_emit_by_name(ev->pipeline, "get-audio-pad", i, &pad); + if (!pad) + continue; + + caps = gst_pad_get_negotiated_caps(pad); + if (!caps) + goto unref_pad_a; + structure = gst_caps_get_structure(caps, 0); + + if (!gst_structure_get_int(structure, "channels", &channels)) + goto unref_caps_a; + if (!gst_structure_get_int(structure, "rate", &samplerate)) + goto unref_caps_a; + + query = gst_query_new_duration(GST_FORMAT_TIME); + if (gst_pad_peer_query(pad, query)) + { + gint64 t; + + gst_query_parse_duration(query, NULL, &t); + length_time = (double)t / (double)GST_SECOND; + } + else + goto unref_query_a; + + astream = calloc(1, sizeof(Emotion_Audio_Stream)); + if (!astream) continue; + ev->audio_streams = eina_list_append(ev->audio_streams, astream); + if (eina_error_get()) + { + free(astream); + continue; + } + + astream->length_time = length_time; + astream->channels = channels; + astream->samplerate = samplerate; + + unref_query_a: + gst_query_unref(query); + unref_caps_a: + gst_caps_unref(caps); + unref_pad_a: + gst_object_unref(pad); + } + + /* Visualization sink */ + if (ev->video_stream_nbr == 0) + { + GstElement *vis = NULL; + Emotion_Video_Stream *vstream; + Emotion_Audio_Stream *astream; + gint flags; + const char *vis_name; + + if (!(vis_name = emotion_visualization_element_name_get(ev->vis))) + { + WRN("pb vis name %d", ev->vis); + goto finalize; + } + + astream = eina_list_data_get(ev->audio_streams); + + vis = gst_element_factory_make(vis_name, "vissink"); + vstream = emotion_video_stream_new(ev); + if (!vstream) + goto finalize; + else + DBG("could not create visualization stream"); + + vstream->length_time = astream->length_time; + vstream->width = 320; + vstream->height = 200; + vstream->fps_num = 25; + vstream->fps_den = 1; + vstream->fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B'); + + g_object_set(G_OBJECT(ev->pipeline), "vis-plugin", vis, NULL); + g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL); + flags |= 0x00000008; + g_object_set(G_OBJECT(ev->pipeline), "flags", flags, NULL); + } + + finalize: + + ev->video_stream_nbr = eina_list_count(ev->video_streams); + ev->audio_stream_nbr = eina_list_count(ev->audio_streams); + + if (ev->video_stream_nbr == 1) + { + Emotion_Video_Stream *vstream; + + vstream = eina_list_data_get(ev->video_streams); + ev->ratio = (double)vstream->width / (double)vstream->height; + _emotion_frame_resize(ev->obj, vstream->width, vstream->height, ev->ratio); + } + + { + /* on recapitule : */ + Emotion_Video_Stream *vstream; + Emotion_Audio_Stream *astream; + + vstream = eina_list_data_get(ev->video_streams); + if (vstream) + { + DBG("video size=%dx%d, fps=%d/%d, " + "fourcc=%"GST_FOURCC_FORMAT", length=%"GST_TIME_FORMAT, + vstream->width, vstream->height, vstream->fps_num, vstream->fps_den, + GST_FOURCC_ARGS(vstream->fourcc), + GST_TIME_ARGS((guint64)(vstream->length_time * GST_SECOND))); + } + + astream = eina_list_data_get(ev->audio_streams); + if (astream) + { + DBG("audio channels=%d, rate=%d, length=%"GST_TIME_FORMAT, + astream->channels, astream->samplerate, + GST_TIME_ARGS((guint64)(astream->length_time * GST_SECOND))); + } + } + + if (ev->metadata) + _free_metadata(ev->metadata); + ev->metadata = calloc(1, sizeof(Emotion_Gstreamer_Metadata)); + + ev->pipeline_parsed = EINA_TRUE; + + em_audio_channel_volume_set(ev, ev->volume); + em_audio_channel_mute_set(ev, ev->audio_mute); + + if (ev->play_started) + { + _emotion_playback_started(ev->obj); + ev->play_started = 0; + } + + _emotion_open_done(ev->obj); + + return EINA_TRUE; +} diff --git a/src/modules/gstreamer/emotion_gstreamer.h b/src/modules/gstreamer/emotion_gstreamer.h new file mode 100644 index 0000000..9c7455d --- /dev/null +++ b/src/modules/gstreamer/emotion_gstreamer.h @@ -0,0 +1,330 @@ +#ifndef __EMOTION_GSTREAMER_H__ +#define __EMOTION_GSTREAMER_H__ + +typedef void (*Evas_Video_Convert_Cb)(unsigned char *evas_data, + const unsigned char *gst_data, + unsigned int w, + unsigned int h, + unsigned int output_height); + +typedef struct _EvasVideoSinkPrivate EvasVideoSinkPrivate; +typedef struct _EvasVideoSink EvasVideoSink; +typedef struct _EvasVideoSinkClass EvasVideoSinkClass; +typedef struct _Emotion_Gstreamer_Video Emotion_Gstreamer_Video; +typedef struct _Emotion_Audio_Stream Emotion_Audio_Stream; +typedef struct _Emotion_Gstreamer_Metadata Emotion_Gstreamer_Metadata; +typedef struct _Emotion_Gstreamer_Buffer Emotion_Gstreamer_Buffer; +typedef struct _Emotion_Gstreamer_Message Emotion_Gstreamer_Message; +typedef struct _Emotion_Video_Stream Emotion_Video_Stream; + +struct _Emotion_Video_Stream +{ + gdouble length_time; + gint width; + gint height; + gint fps_num; + gint fps_den; + guint32 fourcc; + int index; +}; + +struct _Emotion_Audio_Stream +{ + gdouble length_time; + gint channels; + gint samplerate; +}; + +struct _Emotion_Gstreamer_Metadata +{ + char *title; + char *album; + char *artist; + char *genre; + char *comment; + char *year; + char *count; + char *disc_id; +}; + +struct _Emotion_Gstreamer_Video +{ + /* Gstreamer elements */ + GstElement *pipeline; + GstElement *sink; + GstElement *esink; + GstElement *xvsink; + GstElement *tee; + GstElement *convert; + + GstPad *eteepad; + GstPad *xvteepad; + GstPad *xvpad; + Eina_List *threads; + + /* eos */ + GstBus *eos_bus; + + /* Strams */ + Eina_List *video_streams; + Eina_List *audio_streams; + + int video_stream_nbr; + int audio_stream_nbr; + + /* We need to keep a copy of the last inserted buffer as evas doesn't copy YUV data around */ + GstBuffer *last_buffer; + + /* Evas object */ + Evas_Object *obj; + + /* Characteristics of stream */ + double position; + double ratio; + double volume; + + volatile int seek_to; + volatile int get_poslen; + + Emotion_Gstreamer_Metadata *metadata; + +#ifdef HAVE_ECORE_X + Ecore_X_Window win; +#endif + + const char *uri; + + Emotion_Gstreamer_Buffer *send; + + EvasVideoSinkPrivate *sink_data; + + Emotion_Vis vis; + + int in; + int out; + + int frames; + int flapse; + double rtime; + double rlapse; + + struct + { + double width; + double height; + } fill; + + Eina_Bool play : 1; + Eina_Bool play_started : 1; + Eina_Bool video_mute : 1; + Eina_Bool audio_mute : 1; + Eina_Bool pipeline_parsed : 1; + Eina_Bool delete_me : 1; + Eina_Bool samsung : 1; + Eina_Bool kill_buffer : 1; + Eina_Bool stream : 1; + Eina_Bool priority : 1; + + int src_width; + int src_height; +}; + +struct _EvasVideoSink { + /*< private >*/ + GstVideoSink parent; + EvasVideoSinkPrivate *priv; +}; + +struct _EvasVideoSinkClass { + /*< private >*/ + GstVideoSinkClass parent_class; +}; + +struct _EvasVideoSinkPrivate { + EINA_REFCOUNT; + + Evas_Object *o; + + Emotion_Gstreamer_Video *ev; + + Evas_Video_Convert_Cb func; + + unsigned int width; + unsigned int height; + unsigned int source_height; + Evas_Colorspace eformat; + + Eina_Lock m; + Eina_Condition c; + + // If this is TRUE all processing should finish ASAP + // This is necessary because there could be a race between + // unlock() and render(), where unlock() wins, signals the + // GCond, then render() tries to render a frame although + // everything else isn't running anymore. This will lead + // to deadlocks because render() holds the stream lock. + // + // Protected by the buffer mutex + Eina_Bool unlocked : 1; + Eina_Bool samsung : 1; /** ST12 will only define a Samsung specific GstBuffer */ +}; + +struct _Emotion_Gstreamer_Buffer +{ + Emotion_Gstreamer_Video *ev; + EvasVideoSinkPrivate *sink; + + GstBuffer *frame; + + Eina_Bool preroll : 1; + Eina_Bool force : 1; +}; + +struct _Emotion_Gstreamer_Message +{ + Emotion_Gstreamer_Video *ev; + + GstMessage *msg; +}; + +extern Eina_Bool window_manager_video; +extern Eina_Bool debug_fps; +extern int _emotion_gstreamer_log_domain; +extern Eina_Bool _ecore_x_available; +#define DBG(...) EINA_LOG_DOM_DBG(_emotion_gstreamer_log_domain, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(_emotion_gstreamer_log_domain, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(_emotion_gstreamer_log_domain, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(_emotion_gstreamer_log_domain, __VA_ARGS__) +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_emotion_gstreamer_log_domain, __VA_ARGS__) + +#define EVAS_TYPE_VIDEO_SINK evas_video_sink_get_type() + +GType fakeeos_bin_get_type(void); + +#define EVAS_VIDEO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + EVAS_TYPE_VIDEO_SINK, EvasVideoSink)) + +#define EVAS_VIDEO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + EVAS_TYPE_VIDEO_SINK, EvasVideoSinkClass)) + +#define EVAS_IS_VIDEO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + EVAS_TYPE_VIDEO_SINK)) + +#define EVAS_IS_VIDEO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), \ + EVAS_TYPE_VIDEO_SINK)) + +#define EVAS_VIDEO_SINK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + EVAS_TYPE_VIDEO_SINK, EvasVideoSinkClass)) + +#define GST_TYPE_FAKEEOS_BIN fakeeos_bin_get_type() + +GstElement *gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev, + Evas_Object *obj, + const char *uri); + +gboolean gstreamer_plugin_init(GstPlugin *plugin); + +Emotion_Gstreamer_Buffer *emotion_gstreamer_buffer_alloc(EvasVideoSinkPrivate *sink, + GstBuffer *buffer, + Eina_Bool preroll); +void emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send); + +Emotion_Gstreamer_Message *emotion_gstreamer_message_alloc(Emotion_Gstreamer_Video *ev, + GstMessage *msg); +void emotion_gstreamer_message_free(Emotion_Gstreamer_Message *send); +Eina_Bool _emotion_gstreamer_video_pipeline_parse(Emotion_Gstreamer_Video *ev, + Eina_Bool force); + +int em_shutdown(void *video); + +typedef struct _ColorSpace_FourCC_Convertion ColorSpace_FourCC_Convertion; +typedef struct _ColorSpace_Format_Convertion ColorSpace_Format_Convertion; + +struct _ColorSpace_FourCC_Convertion +{ + const char *name; + guint32 fourcc; + Evas_Colorspace eformat; + Evas_Video_Convert_Cb func; + Eina_Bool force_height; +}; + +struct _ColorSpace_Format_Convertion +{ + const char *name; + GstVideoFormat format; + Evas_Colorspace eformat; + Evas_Video_Convert_Cb func; +}; + +extern const ColorSpace_FourCC_Convertion colorspace_fourcc_convertion[]; +extern const ColorSpace_Format_Convertion colorspace_format_convertion[]; + +/** Samsung specific infrastructure - do not touch, do not modify */ +#define MPLANE_IMGB_MAX_COUNT 4 +#define SCMN_IMGB_MAX_PLANE 4 + +typedef struct _GstMultiPlaneImageBuffer GstMultiPlaneImageBuffer; +typedef struct _SCMN_IMGB SCMN_IMGB; + +struct _GstMultiPlaneImageBuffer +{ + GstBuffer buffer; + + /* width of each image plane */ + gint width[MPLANE_IMGB_MAX_COUNT]; + /* height of each image plane */ + gint height[MPLANE_IMGB_MAX_COUNT]; + /* stride of each image plane */ + gint stride[MPLANE_IMGB_MAX_COUNT]; + /* elevation of each image plane */ + gint elevation[MPLANE_IMGB_MAX_COUNT]; + /* user space address of each image plane */ + gpointer uaddr[MPLANE_IMGB_MAX_COUNT]; + /* Index of real address of each image plane, if needs */ + gpointer index[MPLANE_IMGB_MAX_COUNT]; + /* left postion, if needs */ + gint x; + /* top position, if needs */ + gint y; + /* to align memory */ + gint __dummy2; + /* arbitrary data */ + gint data[16]; +}; + +struct _SCMN_IMGB +{ + /* width of each image plane */ + int width[SCMN_IMGB_MAX_PLANE]; + /* height of each image plane */ + int height[SCMN_IMGB_MAX_PLANE]; + /* stride of each image plane */ + int stride[SCMN_IMGB_MAX_PLANE]; + /* elevation of each image plane */ + int elevation[SCMN_IMGB_MAX_PLANE]; + /* user space address of each image plane */ + void * uaddr[SCMN_IMGB_MAX_PLANE]; + /* physical address of each image plane, if needs */ + void * p[SCMN_IMGB_MAX_PLANE]; + /* color space type of image */ + int cs; + /* left postion, if needs */ + int x; + /* top position, if needs */ + int y; + /* to align memory */ + int __dummy2; + /* arbitrary data */ + int data[16]; +}; + +void _evas_video_st12_multiplane(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height __UNUSED__); +void _evas_video_st12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w __UNUSED__, unsigned int h, unsigned int output_height __UNUSED__); + +#endif /* __EMOTION_GSTREAMER_H__ */ diff --git a/src/modules/gstreamer/emotion_sink.c b/src/modules/gstreamer/emotion_sink.c new file mode 100644 index 0000000..b9e2e74 --- /dev/null +++ b/src/modules/gstreamer/emotion_sink.c @@ -0,0 +1,1316 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#define HTTP_STREAM 0 +#define RTSP_STREAM 1 +#include +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + +#include "Emotion.h" +#include "emotion_private.h" +#include "emotion_gstreamer.h" + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE("sink", + GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS(GST_VIDEO_CAPS_YUV("{ I420, YV12, YUY2, NV12, ST12, TM12 }") ";" + GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_BGR ";" GST_VIDEO_CAPS_BGRA)); + +GST_DEBUG_CATEGORY_STATIC(evas_video_sink_debug); +#define GST_CAT_DEFAULT evas_video_sink_debug + +enum { + REPAINT_REQUESTED, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_EVAS_OBJECT, + PROP_WIDTH, + PROP_HEIGHT, + PROP_EV, + PROP_LAST +}; + +static guint evas_video_sink_signals[LAST_SIGNAL] = { 0, }; + +#define _do_init(bla) \ + GST_DEBUG_CATEGORY_INIT(evas_video_sink_debug, \ + "emotion-sink", \ + 0, \ + "emotion video sink") + +GST_BOILERPLATE_FULL(EvasVideoSink, + evas_video_sink, + GstVideoSink, + GST_TYPE_VIDEO_SINK, + _do_init); + + +static void unlock_buffer_mutex(EvasVideoSinkPrivate* priv); +static void evas_video_sink_main_render(void *data); +static void evas_video_sink_samsung_main_render(void *data); + +static void +evas_video_sink_base_init(gpointer g_class) +{ + GstElementClass* element_class; + + element_class = GST_ELEMENT_CLASS(g_class); + gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sinktemplate)); + gst_element_class_set_details_simple(element_class, "Evas video sink", + "Sink/Video", "Sends video data from a GStreamer pipeline to an Evas object", + "Vincent Torri "); +} + +static void +evas_video_sink_init(EvasVideoSink* sink, EvasVideoSinkClass* klass __UNUSED__) +{ + EvasVideoSinkPrivate* priv; + + INF("sink init"); + sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, EVAS_TYPE_VIDEO_SINK, EvasVideoSinkPrivate); + priv->o = NULL; + priv->width = 0; + priv->height = 0; + priv->func = NULL; + priv->eformat = EVAS_COLORSPACE_ARGB8888; + priv->samsung = EINA_FALSE; + eina_lock_new(&priv->m); + eina_condition_new(&priv->c, &priv->m); + priv->unlocked = EINA_FALSE; +} + +/**** Object methods ****/ +static void +_cleanup_priv(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + EvasVideoSinkPrivate* priv; + + priv = data; + + eina_lock_take(&priv->m); + if (priv->o == obj) + priv->o = NULL; + eina_lock_release(&priv->m); +} + +static void +evas_video_sink_set_property(GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + + sink = EVAS_VIDEO_SINK (object); + priv = sink->priv; + + switch (prop_id) { + case PROP_EVAS_OBJECT: + eina_lock_take(&priv->m); + evas_object_event_callback_del(priv->o, EVAS_CALLBACK_FREE, _cleanup_priv); + priv->o = g_value_get_pointer (value); + INF("sink set Evas_Object %p.", priv->o); + evas_object_event_callback_add(priv->o, EVAS_CALLBACK_FREE, _cleanup_priv, priv); + eina_lock_release(&priv->m); + break; + case PROP_EV: + INF("sink set ev."); + eina_lock_take(&priv->m); + priv->ev = g_value_get_pointer (value); + if (priv->ev) + priv->ev->samsung = EINA_TRUE; + eina_lock_release(&priv->m); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + ERR("invalid property"); + break; + } +} + +static void +evas_video_sink_get_property(GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + + sink = EVAS_VIDEO_SINK (object); + priv = sink->priv; + + switch (prop_id) { + case PROP_EVAS_OBJECT: + INF("sink get property."); + eina_lock_take(&priv->m); + g_value_set_pointer(value, priv->o); + eina_lock_release(&priv->m); + break; + case PROP_WIDTH: + INF("sink get width."); + eina_lock_take(&priv->m); + g_value_set_int(value, priv->width); + eina_lock_release(&priv->m); + break; + case PROP_HEIGHT: + INF("sink get height."); + eina_lock_take(&priv->m); + g_value_set_int (value, priv->height); + eina_lock_release(&priv->m); + break; + case PROP_EV: + INF("sink get ev."); + eina_lock_take(&priv->m); + g_value_set_pointer (value, priv->ev); + eina_lock_release(&priv->m); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + ERR("invalide property"); + break; + } +} + +static void +evas_video_sink_dispose(GObject* object) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + + INF("dispose."); + + sink = EVAS_VIDEO_SINK(object); + priv = sink->priv; + + eina_lock_free(&priv->m); + eina_condition_free(&priv->c); + + G_OBJECT_CLASS(parent_class)->dispose(object); +} + + +/**** BaseSink methods ****/ + +gboolean evas_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + GstStructure *structure; + GstVideoFormat format; + guint32 fourcc; + unsigned int i; + + sink = EVAS_VIDEO_SINK(bsink); + priv = sink->priv; + + structure = gst_caps_get_structure(caps, 0); + + if (gst_structure_get_int(structure, "width", (int*) &priv->width) + && gst_structure_get_int(structure, "height", (int*) &priv->height) + && gst_structure_get_fourcc(structure, "format", &fourcc)) + { + priv->source_height = priv->height; + + for (i = 0; colorspace_fourcc_convertion[i].name != NULL; ++i) + if (fourcc == colorspace_fourcc_convertion[i].fourcc) + { + fprintf(stderr, "Found '%s'\n", colorspace_fourcc_convertion[i].name); + priv->eformat = colorspace_fourcc_convertion[i].eformat; + priv->func = colorspace_fourcc_convertion[i].func; + if (colorspace_fourcc_convertion[i].force_height) + { + priv->height = (priv->height >> 1) << 1; + } + if (priv->ev) + priv->ev->kill_buffer = EINA_TRUE; + return TRUE; + } + + if (fourcc == GST_MAKE_FOURCC('S', 'T', '1', '2')) + { + fprintf(stderr, "Found '%s'\n", "ST12"); + priv->eformat = EVAS_COLORSPACE_YCBCR420TM12601_PL; + priv->samsung = EINA_TRUE; + priv->func = NULL; + if (priv->ev) + { + priv->ev->samsung = EINA_TRUE; + priv->ev->kill_buffer = EINA_TRUE; + } + return TRUE; + } + } + + INF("fallback code !"); + if (!gst_video_format_parse_caps(caps, &format, (int*) &priv->width, (int*) &priv->height)) + { + ERR("Unable to parse caps."); + return FALSE; + } + + priv->source_height = priv->height; + + for (i = 0; colorspace_format_convertion[i].name != NULL; ++i) + if (format == colorspace_format_convertion[i].format) + { + fprintf(stderr, "Found '%s'\n", colorspace_format_convertion[i].name); + priv->eformat = colorspace_format_convertion[i].eformat; + priv->func = colorspace_format_convertion[i].func; + if (priv->ev) + priv->ev->kill_buffer = EINA_FALSE; + return TRUE; + } + + ERR("unsupported : %d\n", format); + return FALSE; +} + +static gboolean +evas_video_sink_start(GstBaseSink* base_sink) +{ + EvasVideoSinkPrivate* priv; + gboolean res = TRUE; + + INF("sink start"); + + priv = EVAS_VIDEO_SINK(base_sink)->priv; + eina_lock_take(&priv->m); + if (!priv->o) + res = FALSE; + else + priv->unlocked = EINA_FALSE; + eina_lock_release(&priv->m); + return res; +} + +static gboolean +evas_video_sink_stop(GstBaseSink* base_sink) +{ + EvasVideoSinkPrivate* priv = EVAS_VIDEO_SINK(base_sink)->priv; + + INF("sink stop"); + + unlock_buffer_mutex(priv); + return TRUE; +} + +static gboolean +evas_video_sink_unlock(GstBaseSink* object) +{ + EvasVideoSink* sink; + + INF("sink unlock"); + + sink = EVAS_VIDEO_SINK(object); + + unlock_buffer_mutex(sink->priv); + + return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock, + (object), TRUE); +} + +static gboolean +evas_video_sink_unlock_stop(GstBaseSink* object) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + + sink = EVAS_VIDEO_SINK(object); + priv = sink->priv; + + INF("sink unlock stop"); + + eina_lock_take(&priv->m); + priv->unlocked = FALSE; + eina_lock_release(&priv->m); + + return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock_stop, + (object), TRUE); +} + +static GstFlowReturn +evas_video_sink_preroll(GstBaseSink* bsink, GstBuffer* buffer) +{ + Emotion_Gstreamer_Buffer *send; + EvasVideoSinkPrivate *priv; + EvasVideoSink *sink; + + INF("sink preroll %p [%i]", GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); + + sink = EVAS_VIDEO_SINK(bsink); + priv = sink->priv; + + if (GST_BUFFER_SIZE(buffer) <= 0 && !priv->samsung) + { + WRN("empty buffer"); + return GST_FLOW_OK; + } + + send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_TRUE); + + if (send) + { + if (priv->samsung) + { + if (!priv->func) + { + GstStructure *structure; + GstCaps *caps; + gboolean is_multiplane = FALSE; + + caps = GST_BUFFER_CAPS(buffer); + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_boolean(structure, "multiplane", &is_multiplane); + gst_caps_unref(caps); + + if (is_multiplane) + priv->func = _evas_video_st12_multiplane; + else + priv->func = _evas_video_st12; + } + + ecore_main_loop_thread_safe_call_async(evas_video_sink_samsung_main_render, send); + } + else + ecore_main_loop_thread_safe_call_async(evas_video_sink_main_render, send); + } + + return GST_FLOW_OK; +} + +static GstFlowReturn +evas_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer) +{ + Emotion_Gstreamer_Buffer *send; + EvasVideoSinkPrivate *priv; + EvasVideoSink *sink; + + INF("sink render %p", buffer); + + sink = EVAS_VIDEO_SINK(bsink); + priv = sink->priv; + + eina_lock_take(&priv->m); + + if (priv->unlocked) { + ERR("LOCKED"); + eina_lock_release(&priv->m); + return GST_FLOW_OK; + } + + send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_FALSE); + if (!send) { + eina_lock_release(&priv->m); + return GST_FLOW_ERROR; + } + + if (priv->samsung) + { + if (!priv->func) + { + GstStructure *structure; + GstCaps *caps; + gboolean is_multiplane = FALSE; + + caps = GST_BUFFER_CAPS(buffer); + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_boolean(structure, "multiplane", &is_multiplane); + gst_caps_unref(caps); + + if (is_multiplane) + priv->func = _evas_video_st12_multiplane; + else + priv->func = _evas_video_st12; + } + + ecore_main_loop_thread_safe_call_async(evas_video_sink_samsung_main_render, send); + } + else + ecore_main_loop_thread_safe_call_async(evas_video_sink_main_render, send); + + eina_condition_wait(&priv->c); + eina_lock_release(&priv->m); + + return GST_FLOW_OK; +} + +static void +_update_emotion_fps(Emotion_Gstreamer_Video *ev) +{ + double tim; + + if (!debug_fps) return ; + + tim = ecore_time_get(); + ev->frames++; + + if (ev->rlapse == 0.0) + { + ev->rlapse = tim; + ev->flapse = ev->frames; + } + else if ((tim - ev->rlapse) >= 0.5) + { + printf("FRAME: %i, FPS: %3.1f\n", + ev->frames, + (ev->frames - ev->flapse) / (tim - ev->rlapse)); + ev->rlapse = tim; + ev->flapse = ev->frames; + } +} + +static void +evas_video_sink_samsung_main_render(void *data) +{ + Emotion_Gstreamer_Buffer *send; + Emotion_Video_Stream *vstream; + EvasVideoSinkPrivate *priv = NULL; + GstBuffer* buffer; + unsigned char *evas_data; + const guint8 *gst_data; + GstFormat fmt = GST_FORMAT_TIME; + gint64 pos; + Eina_Bool preroll = EINA_FALSE; + int stride, elevation; + Evas_Coord w, h; + + send = data; + + if (!send) goto exit_point; + + priv = send->sink; + buffer = send->frame; + preroll = send->preroll; + + /* frame after cleanup */ + if (!preroll && !send->ev->last_buffer) + { + priv = NULL; + goto exit_point; + } + + if (!priv || !priv->o || priv->unlocked) + goto exit_point; + + if (send->ev->send) + { + emotion_gstreamer_buffer_free(send->ev->send); + send->ev->send = NULL; + } + + if (!send->ev->stream && !send->force) + { + send->ev->send = send; + _emotion_frame_new(send->ev->obj); + goto exit_stream; + } + + _emotion_gstreamer_video_pipeline_parse(send->ev, EINA_TRUE); + + /* Getting stride to compute the right size and then fill the object properly */ + /* Y => [0] and UV in [1] */ + if (priv->func == _evas_video_st12_multiplane) + { + const GstMultiPlaneImageBuffer *mp_buf = (const GstMultiPlaneImageBuffer *) buffer; + + stride = mp_buf->stride[0]; + elevation = mp_buf->elevation[0]; + priv->width = mp_buf->width[0]; + priv->height = mp_buf->height[0]; + + gst_data = (const guint8 *) mp_buf; + } + else + { + const SCMN_IMGB *imgb = (const SCMN_IMGB *) GST_BUFFER_MALLOCDATA(buffer); + + stride = imgb->stride[0]; + elevation = imgb->elevation[0]; + priv->width = imgb->width[0]; + priv->height = imgb->height[0]; + + gst_data = (const guint8 *) imgb; + } + + evas_object_geometry_get(priv->o, NULL, NULL, &w, &h); + + send->ev->fill.width = (double) stride / priv->width; + send->ev->fill.height = (double) elevation / priv->height; + + evas_object_image_alpha_set(priv->o, 0); + evas_object_image_colorspace_set(priv->o, priv->eformat); + evas_object_image_size_set(priv->o, stride, elevation); + + _update_emotion_fps(send->ev); + + evas_data = evas_object_image_data_get(priv->o, 1); + + if (priv->func) + priv->func(evas_data, gst_data, stride, elevation, elevation); + else + WRN("No way to decode %x colorspace !", priv->eformat); + + evas_object_image_data_set(priv->o, evas_data); + evas_object_image_data_update_add(priv->o, 0, 0, priv->width, priv->height); + evas_object_image_pixels_dirty_set(priv->o, 0); + + if (!preroll && send->ev->play_started) + { + _emotion_playback_started(send->ev->obj); + send->ev->play_started = 0; + } + + if (!send->force) + { + _emotion_frame_new(send->ev->obj); + } + + vstream = eina_list_nth(send->ev->video_streams, send->ev->video_stream_nbr - 1); + + gst_element_query_position(send->ev->pipeline, &fmt, &pos); + send->ev->position = (double)pos / (double)GST_SECOND; + + if (vstream) + { + vstream->width = priv->width; + vstream->height = priv->height; + + _emotion_video_pos_update(send->ev->obj, send->ev->position, vstream->length_time); + } + + send->ev->ratio = (double) priv->width / (double) priv->height; + _emotion_frame_refill(send->ev->obj, send->ev->fill.width, send->ev->fill.height); + _emotion_frame_resize(send->ev->obj, priv->width, priv->height, send->ev->ratio); + + buffer = gst_buffer_ref(buffer); + if (send->ev->last_buffer) gst_buffer_unref(send->ev->last_buffer); + send->ev->last_buffer = buffer; + + exit_point: + emotion_gstreamer_buffer_free(send); + + exit_stream: + if (priv) + { + if (preroll || !priv->o) return; + + if (!priv->unlocked) + eina_condition_signal(&priv->c); + } +} + +static void +evas_video_sink_main_render(void *data) +{ + Emotion_Gstreamer_Buffer *send; + Emotion_Gstreamer_Video *ev = NULL; + Emotion_Video_Stream *vstream; + EvasVideoSinkPrivate *priv = NULL; + GstBuffer *buffer; + unsigned char *evas_data; + GstFormat fmt = GST_FORMAT_TIME; + gint64 pos; + Eina_Bool preroll = EINA_FALSE; + + send = data; + + if (!send) goto exit_point; + + priv = send->sink; + buffer = send->frame; + preroll = send->preroll; + ev = send->ev; + + /* frame after cleanup */ + if (!preroll && !ev->last_buffer) + { + priv = NULL; + goto exit_point; + } + + if (!priv || !priv->o || priv->unlocked) + goto exit_point; + + if (ev->send && send != ev->send) + { + emotion_gstreamer_buffer_free(ev->send); + ev->send = NULL; + } + + if (!ev->stream && !send->force) + { + ev->send = send; + _emotion_frame_new(ev->obj); + evas_object_image_data_update_add(priv->o, 0, 0, priv->width, priv->height); + goto exit_stream; + } + + _emotion_gstreamer_video_pipeline_parse(ev, EINA_TRUE); + + INF("sink main render [%i, %i] (source height: %i)", priv->width, priv->height, priv->source_height); + + evas_object_image_alpha_set(priv->o, 0); + evas_object_image_colorspace_set(priv->o, priv->eformat); + evas_object_image_size_set(priv->o, priv->width, priv->height); + + evas_data = evas_object_image_data_get(priv->o, 1); + + if (priv->func) + priv->func(evas_data, GST_BUFFER_DATA(buffer), priv->width, priv->source_height, priv->height); + else + WRN("No way to decode %x colorspace !", priv->eformat); + + evas_object_image_data_set(priv->o, evas_data); + evas_object_image_data_update_add(priv->o, 0, 0, priv->width, priv->height); + evas_object_image_pixels_dirty_set(priv->o, 0); + + _update_emotion_fps(ev); + + if (!preroll && ev->play_started) + { + _emotion_playback_started(ev->obj); + ev->play_started = 0; + } + + if (!send->force) + { + _emotion_frame_new(ev->obj); + } + + gst_element_query_position(ev->pipeline, &fmt, &pos); + ev->position = (double)pos / (double)GST_SECOND; + + vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1); + + if (vstream) + { + vstream->width = priv->width; + vstream->height = priv->height; + _emotion_video_pos_update(ev->obj, ev->position, vstream->length_time); + } + + ev->ratio = (double) priv->width / (double) priv->height; + + _emotion_frame_resize(ev->obj, priv->width, priv->height, ev->ratio); + + buffer = gst_buffer_ref(buffer); + if (ev->last_buffer) gst_buffer_unref(ev->last_buffer); + ev->last_buffer = buffer; + + exit_point: + emotion_gstreamer_buffer_free(send); + + exit_stream: + if (priv) + { + if (preroll || !priv->o) return; + + if (!priv->unlocked) + eina_condition_signal(&priv->c); + } +} + +static void +unlock_buffer_mutex(EvasVideoSinkPrivate* priv) +{ + priv->unlocked = EINA_TRUE; + + eina_condition_signal(&priv->c); +} + +static void +marshal_VOID__MINIOBJECT(GClosure * closure, GValue * return_value __UNUSED__, + guint n_param_values, const GValue * param_values, + gpointer invocation_hint __UNUSED__, gpointer marshal_data) +{ + typedef void (*marshalfunc_VOID__MINIOBJECT) (gpointer obj, gpointer arg1, gpointer data2); + marshalfunc_VOID__MINIOBJECT callback; + GCClosure *cc; + gpointer data1, data2; + + cc = (GCClosure *) closure; + + g_return_if_fail(n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA(closure)) { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } else { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + callback = (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : cc->callback); + + callback(data1, gst_value_get_mini_object(param_values + 1), data2); +} + +static void +evas_video_sink_class_init(EvasVideoSinkClass* klass) +{ + GObjectClass* gobject_class; + GstBaseSinkClass* gstbase_sink_class; + + gobject_class = G_OBJECT_CLASS(klass); + gstbase_sink_class = GST_BASE_SINK_CLASS(klass); + + g_type_class_add_private(klass, sizeof(EvasVideoSinkPrivate)); + + gobject_class->set_property = evas_video_sink_set_property; + gobject_class->get_property = evas_video_sink_get_property; + + g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT, + g_param_spec_pointer ("evas-object", "Evas Object", + "The Evas object where the display of the video will be done", + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_WIDTH, + g_param_spec_int ("width", "Width", + "The width of the video", + 0, 65536, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_HEIGHT, + g_param_spec_int ("height", "Height", + "The height of the video", + 0, 65536, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_EV, + g_param_spec_pointer ("ev", "Emotion_Gstreamer_Video", + "THe internal data of the emotion object", + G_PARAM_READWRITE)); + + gobject_class->dispose = evas_video_sink_dispose; + + gstbase_sink_class->set_caps = evas_video_sink_set_caps; + gstbase_sink_class->stop = evas_video_sink_stop; + gstbase_sink_class->start = evas_video_sink_start; + gstbase_sink_class->unlock = evas_video_sink_unlock; + gstbase_sink_class->unlock_stop = evas_video_sink_unlock_stop; + gstbase_sink_class->render = evas_video_sink_render; + gstbase_sink_class->preroll = evas_video_sink_preroll; + + evas_video_sink_signals[REPAINT_REQUESTED] = g_signal_new("repaint-requested", + G_TYPE_FROM_CLASS(klass), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + 0, + 0, + marshal_VOID__MINIOBJECT, + G_TYPE_NONE, 1, GST_TYPE_BUFFER); +} + +gboolean +gstreamer_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, + "emotion-sink", + GST_RANK_NONE, + EVAS_TYPE_VIDEO_SINK); +} + +static void +_emotion_gstreamer_pause(void *data, Ecore_Thread *thread) +{ + Emotion_Gstreamer_Video *ev = data; + gboolean res; + + if (ecore_thread_check(thread) || !ev->pipeline) return ; + + gst_element_set_state(ev->pipeline, GST_STATE_PAUSED); + res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + if (res == GST_STATE_CHANGE_NO_PREROLL) + { + gst_element_set_state(ev->pipeline, GST_STATE_PLAYING); + gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + } +} + +static void +_emotion_gstreamer_cancel(void *data, Ecore_Thread *thread) +{ + Emotion_Gstreamer_Video *ev = data; + + ev->threads = eina_list_remove(ev->threads, thread); + + if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT")); + + if (ev->in == ev->out && ev->delete_me) + em_shutdown(ev); +} + +static void +_emotion_gstreamer_end(void *data, Ecore_Thread *thread) +{ + Emotion_Gstreamer_Video *ev = data; + + ev->threads = eina_list_remove(ev->threads, thread); + + if (ev->play) + { + gst_element_set_state(ev->pipeline, GST_STATE_PLAYING); + ev->play_started = 1; + } + + if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT")); + + if (ev->in == ev->out && ev->delete_me) + em_shutdown(ev); + else + _emotion_gstreamer_video_pipeline_parse(data, EINA_TRUE); +} + +static void +_video_resize(void *data, Evas_Object *obj __UNUSED__, const Evas_Video_Surface *surface __UNUSED__, + Evas_Coord w, Evas_Coord h) +{ +#ifdef HAVE_ECORE_X + Emotion_Gstreamer_Video *ev = data; + + ecore_x_window_resize(ev->win, w, h); +#endif + fprintf(stderr, "resize: %i, %i\n", w, h); +} + +static void +_video_move(void *data, Evas_Object *obj __UNUSED__, const Evas_Video_Surface *surface __UNUSED__, + Evas_Coord x, Evas_Coord y) +{ +#ifdef HAVE_ECORE_X + Emotion_Gstreamer_Video *ev = data; + unsigned int pos[2]; + + fprintf(stderr, "move: %i, %i\n", x, y); + pos[0] = x; pos[1] = y; + ecore_x_window_prop_card32_set(ev->win, ECORE_X_ATOM_E_VIDEO_POSITION, pos, 2); +#endif +} + +#if 0 +/* Much better idea to always feed the XvImageSink and let him handle optimizing the rendering as we do */ +static void +_block_pad_unlink_cb(GstPad *pad, gboolean blocked, gpointer user_data) +{ + if (blocked) + { + Emotion_Gstreamer_Video *ev = user_data; + GstEvent *gev; + + gst_pad_unlink(ev->xvteepad, ev->xvpad); + gev = gst_event_new_eos(); + gst_pad_send_event(ev->xvpad, gev); + gst_pad_set_blocked_async(pad, FALSE, _block_pad_unlink_cb, NULL); + } +} + +static void +_block_pad_link_cb(GstPad *pad, gboolean blocked, gpointer user_data) +{ + if (blocked) + { + Emotion_Gstreamer_Video *ev = user_data; + + gst_pad_link(ev->xvteepad, ev->xvpad); + if (ev->play) + gst_element_set_state(ev->xvsink, GST_STATE_PLAYING); + else + gst_element_set_state(ev->xvsink, GST_STATE_PAUSED); + gst_pad_set_blocked_async(pad, FALSE, _block_pad_link_cb, NULL); + } +} +#endif + +static void +_video_show(void *data, Evas_Object *obj __UNUSED__, const Evas_Video_Surface *surface __UNUSED__) +{ +#ifdef HAVE_ECORE_X + Emotion_Gstreamer_Video *ev = data; + + fprintf(stderr, "show xv\n"); + ecore_x_window_show(ev->win); +#endif + /* gst_pad_set_blocked_async(ev->xvteepad, TRUE, _block_pad_link_cb, ev); */ +} + +static void +_video_hide(void *data, Evas_Object *obj __UNUSED__, const Evas_Video_Surface *surface __UNUSED__) +{ +#ifdef HAVE_ECORE_X + Emotion_Gstreamer_Video *ev = data; + + fprintf(stderr, "hide xv\n"); + ecore_x_window_hide(ev->win); +#endif + /* gst_pad_set_blocked_async(ev->xvteepad, TRUE, _block_pad_unlink_cb, ev); */ +} + +static void +_video_update_pixels(void *data, Evas_Object *obj __UNUSED__, const Evas_Video_Surface *surface __UNUSED__) +{ + Emotion_Gstreamer_Video *ev = data; + Emotion_Gstreamer_Buffer *send; + + if (!ev->send) return ; + + send = ev->send; + send->force = EINA_TRUE; + ev->send = NULL; + evas_video_sink_main_render(send); +} + +static void +_image_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + Emotion_Gstreamer_Video *ev = data; + Evas_Coord width, height; + int image_area, src_area; + double ratio; + + evas_object_geometry_get(obj, NULL, NULL, &width, &height); + image_area = width * height; + src_area = ev->src_width * ev->src_height; + ratio = (double)image_area / (double)src_area; + + // when an image is much smaller than original video size, + // add fimcconvert element to the pipeline + if (ratio < 0.8 && !ev->priority && !ev->convert) + { + GstElementFactory *cfactory = NULL; + + cfactory = gst_element_factory_find("fimcconvert"); + if (cfactory) + { + GstElement *convert = NULL; + + convert = gst_element_factory_create(cfactory, NULL); + if (convert) + { + GstElement *queue = NULL; + GstPad *pad, *teepad; + + queue = gst_bin_get_by_name(GST_BIN(ev->sink), "equeue"); + gst_element_unlink(ev->tee, queue); + gst_element_release_request_pad(ev->tee, ev->eteepad); + gst_object_unref(ev->eteepad); + + gst_bin_add(GST_BIN(ev->sink), convert); + gst_element_link_many(ev->tee, convert, queue, NULL); + pad = gst_element_get_pad(convert, "sink"); + teepad = gst_element_get_request_pad(ev->tee, "src%d"); + gst_pad_link(teepad, pad); + gst_object_unref(pad); + + g_object_set(G_OBJECT(convert), "src-width", width, NULL); + g_object_set(G_OBJECT(convert), "src-height", height, NULL); + g_object_set(G_OBJECT(convert), "qos", TRUE, NULL); + gst_element_sync_state_with_parent(convert); + + ev->eteepad = teepad; + ev->convert = convert; + } + } + } + // TODO: when an image is resized(e.g rotation), set size again to fimcconvert + // TODO: fimcconvert has an issue about resetting + //else if (ev->convert) + // { + // g_object_set(G_OBJECT(ev->convert), "src-width", w, NULL); + // g_object_set(G_OBJECT(ev->convert), "src-height", h, NULL); + // } +} + +GstElement * +gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev, + Evas_Object *o, + const char *uri) +{ + GstElement *playbin; + GstElement *bin = NULL; + GstElement *esink = NULL; + GstElement *xvsink = NULL; + GstElement *tee = NULL; + GstElement *queue = NULL; + Evas_Object *obj; + GstPad *pad; + GstPad *teepad; + int flags; + const char *launch; +#if defined HAVE_ECORE_X && defined HAVE_XOVERLAY_H + const char *engine = NULL; + Eina_List *engines; +#endif + + obj = emotion_object_image_get(o); + if (!obj) + { + ERR("Not Evas_Object specified"); + return NULL; + } + + if (!uri) + return NULL; + + launch = emotion_webcam_custom_get(uri); + if (launch) + { + GError *error = NULL; + + playbin = gst_parse_bin_from_description(launch, 1, &error); + if (!playbin) + { + ERR("Unable to setup command : '%s' got error '%s'.", launch, error->message); + g_error_free(error); + return NULL; + } + if (error) + { + WRN("got recoverable error '%s' for command : '%s'.", error->message, launch); + g_error_free(error); + } + } + else + { + playbin = gst_element_factory_make("playbin2", "playbin"); + if (!playbin) + { + ERR("Unable to create 'playbin' GstElement."); + return NULL; + } + } + + bin = gst_bin_new(NULL); + if (!bin) + { + ERR("Unable to create GstBin !"); + goto unref_pipeline; + } + + tee = gst_element_factory_make("tee", NULL); + if (!tee) + { + ERR("Unable to create 'tee' GstElement."); + goto unref_pipeline; + } + +#if defined HAVE_ECORE_X && defined HAVE_XOVERLAY_H + if (window_manager_video) + { + Eina_List *l; + const char *ename; + + engines = evas_render_method_list(); + + EINA_LIST_FOREACH(engines, l, ename) + { + if (evas_render_method_lookup(ename) == + evas_output_method_get(evas_object_evas_get(obj))) + { + engine = ename; + break; + } + } + + if (ev->priority && engine && strstr(engine, "_x11") != NULL) + { + Ecore_Evas *ee; + Evas_Coord x, y, w, h; + Ecore_X_Window win; + Ecore_X_Window parent; + + evas_object_geometry_get(obj, &x, &y, &w, &h); + + ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj)); + + if (w < 4) w = 4; + if (h < 2) h = 2; + + /* Here we really need to have the help of the window manager, this code will change when we update E17. */ + parent = (Ecore_X_Window) ecore_evas_window_get(ee); + fprintf(stderr, "parent: %x\n", parent); + + win = ecore_x_window_new(0, x, y, w, h); + fprintf(stderr, "creating window: %x [%i, %i, %i, %i]\n", win, x, y, w, h); + if (win) + { + Ecore_X_Window_State state[] = { ECORE_X_WINDOW_STATE_SKIP_TASKBAR, ECORE_X_WINDOW_STATE_SKIP_PAGER }; + + ecore_x_netwm_window_state_set(win, state, 2); + ecore_x_window_hide(win); + xvsink = gst_element_factory_make("xvimagesink", NULL); + if (xvsink) + { + unsigned int pos[2]; + +#ifdef HAVE_X_OVERLAY_SET + gst_x_overlay_set_window_handle(GST_X_OVERLAY(xvsink), win); +#else + gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(xvsink), win); +#endif + ev->win = win; + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_VIDEO_PARENT, &parent, 1); + + pos[0] = x; pos[1] = y; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_VIDEO_POSITION, pos, 2); + } + else + { + fprintf(stderr, "destroying win: %x\n", win); + ecore_x_window_free(win); + } + } + } + evas_render_method_list_free(engines); + } +#else +# warning "missing: ecore_x OR xoverlay" +#endif + + esink = gst_element_factory_make("emotion-sink", "sink"); + if (!esink) + { + ERR("Unable to create 'emotion-sink' GstElement."); + goto unref_pipeline; + } + + g_object_set(G_OBJECT(esink), "evas-object", obj, NULL); + g_object_set(G_OBJECT(esink), "ev", ev, NULL); + + evas_object_image_pixels_get_callback_set(obj, NULL, NULL); + evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _image_resize, ev); + + /* We need queue to force each video sink to be in its own thread */ + queue = gst_element_factory_make("queue", "equeue"); + if (!queue) + { + ERR("Unable to create 'queue' GstElement."); + goto unref_pipeline; + } + + gst_bin_add_many(GST_BIN(bin), tee, queue, esink, NULL); + gst_element_link_many(queue, esink, NULL); + + /* link both sink to GstTee */ + pad = gst_element_get_pad(queue, "sink"); + teepad = gst_element_get_request_pad(tee, "src%d"); + gst_pad_link(teepad, pad); + gst_object_unref(pad); + + ev->eteepad = teepad; + + if (xvsink) + { + GstElement *fakeeos; + + queue = gst_element_factory_make("queue", "xvqueue"); + fakeeos = GST_ELEMENT(GST_BIN(g_object_new(GST_TYPE_FAKEEOS_BIN, "name", "eosbin", NULL))); + if (queue && fakeeos) + { + GstPad *queue_pad; + + gst_bin_add_many(GST_BIN(bin), fakeeos, NULL); + + gst_bin_add_many(GST_BIN(fakeeos), queue, xvsink, NULL); + gst_element_link_many(queue, xvsink, NULL); + queue_pad = gst_element_get_pad(queue, "sink"); + gst_element_add_pad(fakeeos, gst_ghost_pad_new("sink", queue_pad)); + + pad = gst_element_get_pad(fakeeos, "sink"); + teepad = gst_element_get_request_pad(tee, "src%d"); + gst_pad_link(teepad, pad); + + xvsink = fakeeos; + + ev->xvteepad = teepad; + ev->xvpad = pad; + } + else + { + if (fakeeos) gst_object_unref(fakeeos); + if (queue) gst_object_unref(queue); + gst_object_unref(xvsink); + xvsink = NULL; + } + } + + teepad = gst_element_get_pad(tee, "sink"); + gst_element_add_pad(bin, gst_ghost_pad_new("sink", teepad)); + gst_object_unref(teepad); + +#define GST_PLAY_FLAG_NATIVE_VIDEO (1 << 6) +#define GST_PLAY_FLAG_DOWNLOAD (1 << 7) +#define GST_PLAY_FLAG_AUDIO (1 << 1) +#define GST_PLAY_FLAG_NATIVE_AUDIO (1 << 5) + + if (launch) + { + g_object_set(G_OBJECT(playbin), "sink", bin, NULL); + } + else + { + g_object_get(G_OBJECT(playbin), "flags", &flags, NULL); + g_object_set(G_OBJECT(playbin), "flags", flags | GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_DOWNLOAD | GST_PLAY_FLAG_NATIVE_AUDIO, NULL); + g_object_set(G_OBJECT(playbin), "video-sink", bin, NULL); + g_object_set(G_OBJECT(playbin), "uri", uri, NULL); + } + + evas_object_image_pixels_get_callback_set(obj, NULL, NULL); + + ev->stream = EINA_TRUE; + + if (xvsink) + { + Evas_Video_Surface video; + + video.version = EVAS_VIDEO_SURFACE_VERSION; + video.data = ev; + video.parent = NULL; + video.move = _video_move; + video.resize = _video_resize; + video.show = _video_show; + video.hide = _video_hide; + video.update_pixels = _video_update_pixels; + + evas_object_image_video_surface_set(obj, &video); + ev->stream = EINA_FALSE; + } + + eina_stringshare_replace(&ev->uri, uri); + ev->pipeline = playbin; + ev->sink = bin; + ev->esink = esink; + ev->xvsink = xvsink; + ev->tee = tee; + ev->threads = eina_list_append(ev->threads, + ecore_thread_run(_emotion_gstreamer_pause, + _emotion_gstreamer_end, + _emotion_gstreamer_cancel, + ev)); + + /** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */ + /** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */ + if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(playbin), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT")); + + return playbin; + + unref_pipeline: + gst_object_unref(xvsink); + gst_object_unref(esink); + gst_object_unref(tee); + gst_object_unref(bin); + gst_object_unref(playbin); + return NULL; +} diff --git a/src/modules/xine/Makefile.am b/src/modules/xine/Makefile.am new file mode 100644 index 0000000..baf8fec --- /dev/null +++ b/src/modules/xine/Makefile.am @@ -0,0 +1,31 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/modules \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EMOTION_CFLAGS@ \ +@EMOTION_CPPFLAGS@ \ +@EFL_EMOTION_BUILD@ \ +@XINE_CFLAGS@ + +if EMOTION_BUILD_XINE +if !EMOTION_STATIC_BUILD_XINE + +pkgdir = $(libdir)/emotion + +pkg_LTLIBRARIES = xine.la + +xine_la_SOURCES = \ +emotion_xine.c \ +emotion_xine.h \ +emotion_xine_vo_out.c +xine_la_LIBADD = @EMOTION_LIBS@ @XINE_LIBS@ $(top_builddir)/src/lib/libemotion.la -lpthread +xine_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +xine_la_LIBTOOLFLAGS = --tag=disable-static + +endif +endif diff --git a/src/modules/xine/emotion_xine.c b/src/modules/xine/emotion_xine.c new file mode 100644 index 0000000..dd4a3a5 --- /dev/null +++ b/src/modules/xine/emotion_xine.c @@ -0,0 +1,1723 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "Emotion.h" +#include "emotion_private.h" +#include "emotion_xine.h" + +int _emotion_xine_log_domain = -1; + +/* module api */ +static unsigned char em_init (Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt); +static int em_shutdown (void *ef); +static unsigned char em_file_open (const char *file, Evas_Object *obj, void *ef); +static void em_file_close (void *ef); +static void em_play (void *ef, double pos); +static void em_stop (void *ef); +static void em_size_get (void *ef, int *w, int *h); +static void em_pos_set (void *ef, double pos); +static double em_buffer_size_get (void *ef); +static double em_len_get (void *ef); +static int em_fps_num_get (void *ef); +static int em_fps_den_get (void *ef); +static double em_fps_get (void *ef); +static double em_pos_get (void *ef); +static void em_vis_set (void *ef, Emotion_Vis vis); +static Emotion_Vis em_vis_get (void *ef); +static Eina_Bool em_vis_supported (void *ef, Emotion_Vis vis); +static double em_ratio_get (void *ef); +static int em_seekable (void *ef); +static void em_frame_done (void *ef); +static Emotion_Format em_format_get (void *ef); +static void em_video_data_size_get (void *ef, int *w, int *h); +static int em_yuv_rows_get (void *ef, int w, int h, unsigned char **yrows, unsigned char **urows, unsigned char **vrows); +static int em_bgra_data_get (void *ef, unsigned char **bgra_data); +static void em_event_feed (void *ef, int event); +static void em_event_mouse_button_feed (void *ef, int button, int x, int y); +static void em_event_mouse_move_feed (void *ef, int x, int y); +static int em_video_channel_count (void *ef); +static void em_video_channel_set (void *ef, int channel); +static int em_video_channel_get (void *ef); +static const char *em_video_channel_name_get (void *ef, int channel); +static void em_video_channel_mute_set (void *ef, int mute); +static int em_video_channel_mute_get (void *ef); +static int em_audio_channel_count (void *ef); +static void em_audio_channel_set (void *ef, int channel); +static int em_audio_channel_get (void *ef); +static const char *em_audio_channel_name_get (void *ef, int channel); +static void em_audio_channel_mute_set (void *ef, int mute); +static int em_audio_channel_mute_get (void *ef); +static void em_audio_channel_volume_set(void *ef, double vol); +static double em_audio_channel_volume_get(void *ef); +static int em_spu_channel_count (void *ef); +static void em_spu_channel_set (void *ef, int channel); +static int em_spu_channel_get (void *ef); +static const char *em_spu_channel_name_get (void *ef, int channel); +static void em_spu_channel_mute_set (void *ef, int mute); +static int em_spu_channel_mute_get (void *ef); +static int em_chapter_count (void *ef); +static void em_chapter_set (void *ef, int chapter); +static int em_chapter_get (void *ef); +static const char *em_chapter_name_get (void *ef, int chapter); +static void em_speed_set (void *ef, double speed); +static double em_speed_get (void *ef); +static int em_eject (void *ef); +static const char *em_meta_get (void *ef, int meta); + +/* internal util calls */ +static void *_em_slave (void *par); +static void _em_slave_event (void *data, int type, void *arg); +static Eina_Bool _em_fd_active (void *data, Ecore_Fd_Handler *fdh); +static void _em_event (void *data, const xine_event_t *event); +static void _em_module_event (void *data, int type); +static Eina_Bool _em_fd_ev_active (void *data, Ecore_Fd_Handler *fdh); +//static int _em_timer (void *data); +static void *_em_get_pos_len_th(void *par); +static void _em_get_pos_len (Emotion_Xine_Video *ev); + +extern plugin_info_t emotion_xine_plugin_info[]; + +/* this is a slave controller thread for the xine module - libxine loves + * to deadlock, internally stall and otherwise have unpredictable behavior + * if we use the main process thread for many things - so a lot will be + * farmed off to this slave. its job is to handle opening, closing, file + * opening, recoder init etc. and all sorts of things can that often block. + * anything this thread needs to return, it will return via the event pipe. + */ +static void * +_em_slave(void *par) +{ + Emotion_Xine_Video *ev; + void *buf[2]; + int len; + + ev = (Emotion_Xine_Video *)par; + while ((len = read(ev->fd_slave_read, buf, sizeof(buf))) > 0) + { + if (len == sizeof(buf)) + { + Emotion_Xine_Event *eev; + + ev = buf[0]; + eev = buf[1]; + switch (eev->mtype) + { + case 0: /* noop */ + break; + case 1: /* init */ + { + ev->decoder = xine_new(); + xine_init(ev->decoder); + xine_register_plugins(ev->decoder, emotion_xine_plugin_info); + if (1) + { + xine_cfg_entry_t cf; + if (xine_config_lookup_entry(ev->decoder, "input.dvd_use_readahead", &cf)) + { + cf.num_value = 1; // 0 or 1 + xine_config_update_entry(ev->decoder, &cf); + } + } + DBG("OPEN VIDEO PLUGIN..."); + if (!ev->opt_no_video) + ev->video = xine_open_video_driver(ev->decoder, "emotion", + XINE_VISUAL_TYPE_NONE, ev); + DBG("RESULT: xine_open_video_driver() = %p", ev->video); + // Let xine autodetect the best audio output driver + if (!ev->opt_no_audio) + ev->audio = xine_open_audio_driver(ev->decoder, NULL, ev); + // ev->audio = xine_open_audio_driver(ev->decoder, "oss", ev); + // dont use alsa - alsa has oss emulation. + // ev->audio = xine_open_audio_driver(ev->decoder, "alsa", ev); + // ev->audio = xine_open_audio_driver(ev->decoder, "arts", ev); + // ev->audio = xine_open_audio_driver(ev->decoder, "esd", ev); + ev->stream = xine_stream_new(ev->decoder, ev->audio, ev->video); + ev->queue = xine_event_new_queue(ev->stream); + xine_event_create_listener_thread(ev->queue, _em_event, ev); + ev->opening = 0; + ev->play_ok = 1; + _em_module_event(ev, 1); /* event - open done */ + } + break; + case 3: /* shutdown */ + { + _em_module_event(ev, 3); + DBG("shutdown stop"); + xine_stop(ev->stream); + // pthread_mutex_lock(&(ev->get_pos_len_mutex)); + if (!ev->get_pos_thread_deleted) + { + DBG("closing get_pos thread, %p", ev); + pthread_mutex_lock(&(ev->get_pos_len_mutex)); + pthread_cond_broadcast(&(ev->get_pos_len_cond)); + pthread_mutex_unlock(&(ev->get_pos_len_mutex)); + while (ev->get_poslen); + } + DBG("dispose %p", ev); + xine_dispose(ev->stream); + DBG("dispose evq %p", ev); + xine_event_dispose_queue(ev->queue); + DBG("close video drv %p", ev); + if (ev->video) xine_close_video_driver(ev->decoder, ev->video); + DBG("wait for vo to go"); + while (ev->have_vo); + DBG("vo gone"); + DBG("close audio drv %p", ev); + if (ev->audio) xine_close_audio_driver(ev->decoder, ev->audio); + DBG("xine exit %p", ev); + xine_exit(ev->decoder); + DBG("DONE %p", ev); + close(ev->fd_write); + close(ev->fd_read); + close(ev->fd_ev_write); + close(ev->fd_ev_read); + close(ev->fd_slave_write); + close(ev->fd_slave_read); + ev->closing = 0; + if (eev->xine_event) free(eev->xine_event); + free(eev); + free(ev); + return NULL; + } + break; + case 2: /* file open */ + { + int pos_stream = 0; + int pos_time = 0; + int length_time = 0; + uint32_t v; + char *file; + + file = eev->xine_event; + DBG("OPEN STREAM %s", file); + if (xine_open(ev->stream, file)) + { + if (xine_get_pos_length(ev->stream, &pos_stream, &pos_time, &length_time)) + { + if (length_time == 0) + { + ev->pos = (double)pos_stream / 65535; + ev->len = 1.0; + ev->no_time = 1; + } + else + { + ev->pos = 0.0; + ev->len = (double)length_time / 1000.0; + } + } + else + { + ev->pos = 0.0; + ev->len = 1.0; + } + v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_FRAME_DURATION); + if (v > 0) ev->fps = 90000.0 / (double)v; + v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_WIDTH); + ev->w = v; + v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_HEIGHT); + ev->h = v; + v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_RATIO); + ev->ratio = (double)v / 10000.0; + ev->just_loaded = 1; + ev->get_poslen = 0; + xine_set_param(ev->stream, XINE_PARAM_AUDIO_VOLUME, ev->volume * 100); + } + _em_module_event(ev, 2); /* event - open done */ + } + break; + case 11: /* file close */ + { + DBG("done %p", ev); + em_frame_done(ev); + DBG("stop %p", ev); + xine_stop(ev->stream); + DBG("close %p", ev); + xine_close(ev->stream); + DBG("close done %p", ev); + _em_module_event(ev, 11); + } + break; + case 4: /* play */ + { + double pos; + int pos_stream, pos_time, length_time; + + pos = *((double *)eev->xine_event); + if ((xine_get_param(ev->stream, XINE_PARAM_SPEED) == XINE_SPEED_PAUSE) && + (pos == ev->pos) && + (!ev->just_loaded)) + { + xine_set_param(ev->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL); + } + else + { + if (ev->no_time) + xine_play(ev->stream, pos * 65535, 0); + else + xine_play(ev->stream, 0, pos * 1000); + } + ev->just_loaded = 0; + + if (xine_get_pos_length(ev->stream, + &pos_stream, + &pos_time, + &length_time)) + { + if (length_time == 0) + { + ev->pos = (double)pos_stream / 65535; + ev->len = 1.0; + ev->no_time = 1; + } + else + { + ev->pos = (double)pos_time / 1000.0; + ev->len = (double)length_time / 1000.0; + } + } + _em_module_event(ev, 4); + } + break; + case 5: /* stop */ + { + xine_set_param(ev->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE); + _em_module_event(ev, 5); + } + break; + case 6: /* seek */ + { + double pos; + + pos = *((double *)eev->xine_event); + if (ev->no_time) + xine_play(ev->stream, pos * 65535, 0); + else + xine_play(ev->stream, 0, pos * 1000); + if (!ev->play) + xine_set_param(ev->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE); + _em_module_event(ev, 6); + } + break; + case 7: /* eject */ + { + xine_eject(ev->stream); + _em_module_event(ev, 7); + } + break; + case 8: /* spu mute */ + { + xine_set_param(ev->stream, XINE_PARAM_IGNORE_SPU, ev->spu_mute); + _em_module_event(ev, 8); + } + break; + case 9: /* channel */ + { + xine_set_param(ev->stream, XINE_PARAM_SPU_CHANNEL, ev->spu_channel); + _em_module_event(ev, 9); + } + break; + case 10: /* vol */ + { + xine_set_param(ev->stream, XINE_PARAM_AUDIO_VOLUME, ev->volume * 100); + _em_module_event(ev, 10); + } + break; + case 12: /* audio mute */ + { + xine_set_param(ev->stream, XINE_PARAM_AUDIO_MUTE, ev->audio_mute); + } + break; + case 13: /* audio mute */ + { + xine_set_param(ev->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, ev->audio_channel); + } + break; + case 14: /* audio mute */ + { + xine_set_param(ev->stream, XINE_PARAM_VIDEO_CHANNEL, ev->video_channel); + } + break; + default: + break; + } + if (eev->xine_event) free(eev->xine_event); + free(eev); + } + } + return NULL; +} +static void +_em_slave_event(void *data, int type, void *arg) +{ + void *buf[2]; + Emotion_Xine_Event *new_ev; + Emotion_Xine_Video *ev; + + ev = data; + new_ev = calloc(1, sizeof(Emotion_Xine_Event)); + if (!new_ev) return; + new_ev->mtype = type; + new_ev->type = -1; + new_ev->xine_event = arg; + buf[0] = data; + buf[1] = new_ev; + if (write(ev->fd_slave_write, buf, sizeof(buf)) < 0) perror("write"); +} + +static unsigned char +em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt) +{ + Emotion_Xine_Video *ev; + int fds[2]; + + if (!emotion_video) return 0; + + ev = calloc(1, sizeof(Emotion_Xine_Video)); + if (!ev) return 0; + ev->obj = obj; + + if (pipe(fds) == 0) + { + ev->fd_read = fds[0]; + ev->fd_write = fds[1]; + fcntl(ev->fd_read, F_SETFL, O_NONBLOCK); + ev->fd_handler = ecore_main_fd_handler_add(ev->fd_read, ECORE_FD_READ, + _em_fd_active, ev, + NULL, NULL); + ecore_main_fd_handler_active_set(ev->fd_handler, ECORE_FD_READ); + } + if (pipe(fds) == 0) + { + ev->fd_ev_read = fds[0]; + ev->fd_ev_write = fds[1]; + fcntl(ev->fd_ev_read, F_SETFL, O_NONBLOCK); + ev->fd_ev_handler = ecore_main_fd_handler_add(ev->fd_ev_read, + ECORE_FD_READ, _em_fd_ev_active, ev, NULL, NULL); + ecore_main_fd_handler_active_set(ev->fd_ev_handler, ECORE_FD_READ); + } + if (pipe(fds) == 0) + { + ev->fd_slave_read = fds[0]; + ev->fd_slave_write = fds[1]; + fcntl(ev->fd_slave_write, F_SETFL, O_NONBLOCK); + } + ev->volume = 0.8; + ev->delete_me = 0; + ev->get_pos_thread_deleted = 0; + ev->opening = 1; + ev->play_ok = 0; + + if (opt) + { + ev->opt_no_audio = opt->no_audio; + ev->opt_no_video = opt->no_video; + } + + pthread_cond_init(&(ev->get_pos_len_cond), NULL); + pthread_mutex_init(&(ev->get_pos_len_mutex), NULL); + pthread_create(&ev->get_pos_len_th, NULL, _em_get_pos_len_th, ev); + + pthread_create(&ev->slave_th, NULL, _em_slave, ev); + pthread_detach(ev->slave_th); + _em_slave_event(ev, 1, NULL); + + ev->buffer = 1.0; + + *emotion_video = ev; + return 1; +} + +static int +em_shutdown(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + ev->closing = 1; + ev->delete_me = 1; + DBG("del fds %p", ev); + ecore_main_fd_handler_del(ev->fd_handler); + ev->fd_handler = NULL; + ecore_main_fd_handler_del(ev->fd_ev_handler); + ev->fd_ev_handler = NULL; + if (ev->anim) + { + ecore_animator_del(ev->anim); + ev->anim = NULL; + } + + ev->closing = 1; + _em_slave_event(ev, 3, NULL); + DBG("done %p", ev); + return 1; +} + +static unsigned char +em_file_open(const char *file, Evas_Object *obj __UNUSED__, void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (!ev) return 0; + _em_slave_event(ev, 2, strdup(file)); + return 1; +} + +static void +em_file_close(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (!ev) return; + _em_slave_event(ev, 11, NULL); +} + +static void +em_play(void *ef, double pos) +{ + Emotion_Xine_Video *ev; + double *ppos; + + ev = (Emotion_Xine_Video *)ef; + ev->play = 1; + ev->play_ok = 0; + ppos = malloc(sizeof(double)); + *ppos = pos; + _em_slave_event(ev, 4, ppos); +} + +static void +em_stop(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + ev->play = 0; + ev->play_ok = 0; + _em_slave_event(ev, 5, NULL); +} + +static void +em_size_get(void *ef, int *w, int *h) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (w) *w = ev->w; + if (h) *h = ev->h; +} + +static void +em_pos_set(void *ef, double pos) +{ + Emotion_Xine_Video *ev; + double *ppos; + + ev = (Emotion_Xine_Video *)ef; + ppos = malloc(sizeof(double)); + *ppos = pos; + _em_slave_event(ev, 6, ppos); +} + +static double +em_len_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + return ev->len; +} + +static double +em_buffer_size_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + return ev->buffer; +} + +static int +em_fps_num_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + return (int)(ev->fps * 10000.0); +} + +static int +em_fps_den_get(void *ef __UNUSED__) +{ + return 10000; +} + +static double +em_fps_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + return ev->fps; +} + +static double +em_pos_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + _em_get_pos_len(ev); + return ev->pos; +} + +static void +em_vis_set(void *ef, Emotion_Vis vis) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->vis == vis) return; + ev->vis = vis; +} + +static Emotion_Vis +em_vis_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + + return ev->vis; +} + +static Eina_Bool +em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__) +{ + return EINA_FALSE; +} + +static double +em_ratio_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + return ev->ratio; +} + +static int +em_video_handled(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + return (xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_VIDEO) && + xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_HANDLED)); +} + +static int +em_audio_handled(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + return (xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_AUDIO) && + xine_get_stream_info(ev->stream, XINE_STREAM_INFO_AUDIO_HANDLED)); +} + +static int +em_seekable(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + return xine_get_stream_info(ev->stream, XINE_STREAM_INFO_SEEKABLE); +} + +static void +em_frame_done(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->cur_frame) + { + ev->fq--; + if (ev->cur_frame->done_func) + ev->cur_frame->done_func(ev->cur_frame->done_data); + ev->cur_frame = NULL; + } +} + +static Emotion_Format +em_format_get(void *ef) +{ + Emotion_Xine_Video *ev; + volatile Emotion_Xine_Video_Frame *fr; + + ev = (Emotion_Xine_Video *)ef; + fr = ev->cur_frame; + if (fr) return fr->format; + return EMOTION_FORMAT_YV12; +} + +static void +em_video_data_size_get(void *ef, int *w, int *h) +{ + Emotion_Xine_Video *ev; + volatile Emotion_Xine_Video_Frame *fr; + + ev = (Emotion_Xine_Video *)ef; + fr = ev->cur_frame; + if (!fr) + { + if (w) *w = 0; + if (h) *h = 0; + return; + } + if (w) *w = fr->w; + if (h) *h = fr->h; +} + +static int +em_yuv_rows_get(void *ef, int w __UNUSED__, int h, unsigned char **yrows, unsigned char **urows, unsigned char **vrows) +{ + Emotion_Xine_Video *ev; + volatile Emotion_Xine_Video_Frame *fr; + + ev = (Emotion_Xine_Video *)ef; + fr = ev->cur_frame; + if (!fr) return 0; + if (fr->y) + { + int i; + + for (i = 0; i < h; i++) yrows[i] = fr->y + (i * fr->y_stride); + for (i = 0; i < (h / 2); i++) urows[i] = fr->u + (i * fr->u_stride); + for (i = 0; i < (h / 2); i++) vrows[i] = fr->v + (i * fr->v_stride); + return 1; + } + return 0; +} + +static int +em_bgra_data_get(void *ef, unsigned char **bgra_data) +{ + Emotion_Xine_Video *ev; + volatile Emotion_Xine_Video_Frame *fr; + + ev = (Emotion_Xine_Video *)ef; + fr = ev->cur_frame; + if (!fr) return 0; + if (fr->bgra_data) + { + *bgra_data = fr->bgra_data; + return 1; + } + return 0; +} + +static void +em_event_feed(void *ef, int event) +{ + Emotion_Xine_Video *ev; + xine_event_t xine_event; + + ev = (Emotion_Xine_Video *)ef; + if ((ev->opening) || (!ev->play_ok)) return; + xine_event.data_length = 0; + xine_event.data = NULL; + xine_event.stream = ev->stream; + gettimeofday(&xine_event.tv, NULL); + switch (event) + { + case EMOTION_EVENT_MENU1: + xine_event.type = XINE_EVENT_INPUT_MENU1; + break; + case EMOTION_EVENT_MENU2: + xine_event.type = XINE_EVENT_INPUT_MENU2; + break; + case EMOTION_EVENT_MENU3: + xine_event.type = XINE_EVENT_INPUT_MENU3; + break; + case EMOTION_EVENT_MENU4: + xine_event.type = XINE_EVENT_INPUT_MENU4; + break; + case EMOTION_EVENT_MENU5: + xine_event.type = XINE_EVENT_INPUT_MENU5; + break; + case EMOTION_EVENT_MENU6: + xine_event.type = XINE_EVENT_INPUT_MENU6; + break; + case EMOTION_EVENT_MENU7: + xine_event.type = XINE_EVENT_INPUT_MENU7; + break; + case EMOTION_EVENT_UP: + xine_event.type = XINE_EVENT_INPUT_UP; + break; + case EMOTION_EVENT_DOWN: + xine_event.type = XINE_EVENT_INPUT_DOWN; + break; + case EMOTION_EVENT_LEFT: + xine_event.type = XINE_EVENT_INPUT_LEFT; + break; + case EMOTION_EVENT_RIGHT: + xine_event.type = XINE_EVENT_INPUT_RIGHT; + break; + case EMOTION_EVENT_SELECT: + xine_event.type = XINE_EVENT_INPUT_SELECT; + break; + case EMOTION_EVENT_NEXT: + xine_event.type = XINE_EVENT_INPUT_NEXT; + break; + case EMOTION_EVENT_PREV: + xine_event.type = XINE_EVENT_INPUT_PREVIOUS; + break; + case EMOTION_EVENT_ANGLE_NEXT: + xine_event.type = XINE_EVENT_INPUT_ANGLE_NEXT; + break; + case EMOTION_EVENT_ANGLE_PREV: + xine_event.type = XINE_EVENT_INPUT_ANGLE_PREVIOUS; + break; + case EMOTION_EVENT_FORCE: + xine_event.type = XINE_EVENT_INPUT_BUTTON_FORCE; + break; + case EMOTION_EVENT_0: + xine_event.type = XINE_EVENT_INPUT_NUMBER_0; + break; + case EMOTION_EVENT_1: + xine_event.type = XINE_EVENT_INPUT_NUMBER_1; + break; + case EMOTION_EVENT_2: + xine_event.type = XINE_EVENT_INPUT_NUMBER_2; + break; + case EMOTION_EVENT_3: + xine_event.type = XINE_EVENT_INPUT_NUMBER_3; + break; + case EMOTION_EVENT_4: + xine_event.type = XINE_EVENT_INPUT_NUMBER_4; + break; + case EMOTION_EVENT_5: + xine_event.type = XINE_EVENT_INPUT_NUMBER_5; + break; + case EMOTION_EVENT_6: + xine_event.type = XINE_EVENT_INPUT_NUMBER_6; + break; + case EMOTION_EVENT_7: + xine_event.type = XINE_EVENT_INPUT_NUMBER_7; + break; + case EMOTION_EVENT_8: + xine_event.type = XINE_EVENT_INPUT_NUMBER_8; + break; + case EMOTION_EVENT_9: + xine_event.type = XINE_EVENT_INPUT_NUMBER_9; + break; + case EMOTION_EVENT_10: + xine_event.type = XINE_EVENT_INPUT_NUMBER_10_ADD; + break; + default: + return; + break; + } + xine_event_send(ev->stream, &xine_event); +} + +static void +em_event_mouse_button_feed(void *ef, int button __UNUSED__, int x, int y) +{ + Emotion_Xine_Video *ev; + xine_event_t xine_event; + xine_input_data_t xine_input; + + ev = (Emotion_Xine_Video *)ef; + if ((ev->opening) || (!ev->play_ok)) return; + xine_event.stream = ev->stream; + gettimeofday(&xine_event.tv, NULL); + xine_event.type = XINE_EVENT_INPUT_MOUSE_BUTTON; + xine_input.button = 1; + xine_input.x = x; + xine_input.y = y; + xine_event.data = &xine_input; + xine_event.data_length = sizeof(xine_input); + xine_event_send(ev->stream, &xine_event); +} + +static void +em_event_mouse_move_feed(void *ef, int x, int y) +{ + Emotion_Xine_Video *ev; + xine_event_t xine_event; + xine_input_data_t xine_input; + + ev = (Emotion_Xine_Video *)ef; + if ((ev->opening) || (!ev->play_ok)) return; + xine_event.stream = ev->stream; + gettimeofday(&xine_event.tv, NULL); + xine_event.type = XINE_EVENT_INPUT_MOUSE_MOVE; + xine_input.button = 0; + xine_input.x = x; + xine_input.y = y; + xine_event.data = &xine_input; + xine_event.data_length = sizeof(xine_input); + xine_event_send(ev->stream, &xine_event); +} + +static int +em_video_channel_count(void *ef) +{ + Emotion_Xine_Video *ev; + int v; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_CHANNELS); + if ((v < 1) && + xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_VIDEO)) return 1; + return v; +} + +static void +em_video_channel_set(void *ef, int channel) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (channel < 0) channel = 0; + ev->video_channel = channel; + _em_slave_event(ev, 14, NULL); +} + +static int +em_video_channel_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + return xine_get_param(ev->stream, XINE_PARAM_VIDEO_CHANNEL); +} + +static const char * +em_video_channel_name_get(void *ef __UNUSED__, int channel __UNUSED__) +{ + return NULL; +} + +static void +em_video_channel_mute_set(void *ef, int mute) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + ev->video_mute = mute; +} + +static int +em_video_channel_mute_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + return ev->video_mute; +} + +static int +em_audio_channel_count(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + return xine_get_stream_info(ev->stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL); +} + +static void +em_audio_channel_set(void *ef, int channel) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (channel < -1) channel = -1; + ev->audio_channel = channel; + _em_slave_event(ev, 13, NULL); +} + +static int +em_audio_channel_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + return xine_get_param(ev->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL); +} + +static const char * +em_audio_channel_name_get(void *ef, int channel) +{ + Emotion_Xine_Video *ev; + static char lang[XINE_LANG_MAX + 1]; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening) return NULL; + lang[0] = 0; + if (xine_get_audio_lang(ev->stream, channel, lang)) return lang; + return NULL; +} + +static void +em_audio_channel_mute_set(void *ef, int mute) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + ev->audio_mute = mute; + _em_slave_event(ev, 12, NULL); +} + +static int +em_audio_channel_mute_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + return ev->audio_mute; +} + +static void +em_audio_channel_volume_set(void *ef, double vol) +{ + Emotion_Xine_Video *ev; + + if (vol < 0.0) vol = 0.0; + else if (vol > 1.0) vol = 1.0; + + ev = (Emotion_Xine_Video *)ef; + ev->volume = vol; + _em_slave_event(ev, 10, NULL); +} + +static double +em_audio_channel_volume_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return ev->volume; + ev->volume = xine_get_param(ev->stream, XINE_PARAM_AUDIO_VOLUME) / 100.0; + return ev->volume; +} + +static int +em_spu_channel_count(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + return xine_get_stream_info(ev->stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL); +} + +static void +em_spu_channel_set(void *ef, int channel) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (channel < 0) channel = 0; + ev->spu_channel = channel; + _em_slave_event(ev, 9, NULL); +} + +static int +em_spu_channel_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + return xine_get_param(ev->stream, XINE_PARAM_SPU_CHANNEL); +} + +static const char * +em_spu_channel_name_get(void *ef, int channel) +{ + Emotion_Xine_Video *ev; + static char lang[XINE_LANG_MAX + 1]; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening) return NULL; + lang[0] = 0; + if (xine_get_spu_lang(ev->stream, channel, lang)) return lang; + return NULL; +} + +static void +em_spu_channel_mute_set(void *ef, int mute) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + ev->spu_mute = mute; + _em_slave_event(ev, 8, NULL); +} + +static int +em_spu_channel_mute_get(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + return ev->spu_mute; +} + +static int +em_chapter_count(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->opening || (!ev->play_ok)) return 0; + if (xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_CHAPTERS)) + return 99; + return 0; +} + +static void +em_chapter_set(void *ef __UNUSED__, int chapter __UNUSED__) +{ +} + +static int +em_chapter_get(void *ef __UNUSED__) +{ + return 0; +} + +static const char * +em_chapter_name_get(void *ef __UNUSED__, int chapter __UNUSED__) +{ + return NULL; +} + +static void +em_speed_set(void *ef __UNUSED__, double speed __UNUSED__) +{ +} + +static double +em_speed_get(void *ef __UNUSED__) +{ + return 1.0; +} + +static int +em_eject(void *ef) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + _em_slave_event(ev, 7, NULL); + return 1; +} + +static const char * +em_meta_get(void *ef, int meta) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if ((ev->opening) || (!ev->play_ok)) return NULL; + switch (meta) + { + case META_TRACK_TITLE: + return xine_get_meta_info(ev->stream, XINE_META_INFO_TITLE); + break; + case META_TRACK_ARTIST: + return xine_get_meta_info(ev->stream, XINE_META_INFO_ARTIST); + break; + case META_TRACK_GENRE: + return xine_get_meta_info(ev->stream, XINE_META_INFO_GENRE); + break; + case META_TRACK_COMMENT: + return xine_get_meta_info(ev->stream, XINE_META_INFO_COMMENT); + break; + case META_TRACK_ALBUM: + return xine_get_meta_info(ev->stream, XINE_META_INFO_ALBUM); + break; + case META_TRACK_YEAR: + return xine_get_meta_info(ev->stream, XINE_META_INFO_YEAR); + break; + case META_TRACK_DISCID: + return xine_get_meta_info(ev->stream, XINE_META_INFO_CDINDEX_DISCID); + break; + default: + break; + } + return NULL; +} + +static Eina_Bool +_em_fd_active(void *data, Ecore_Fd_Handler *fdh) +{ + void *buf; + int fd, len; + Emotion_Xine_Video_Frame *fr; + + fd = ecore_main_fd_handler_fd_get(fdh); + while ((len = read(fd, &buf, sizeof(buf))) > 0) + { + if (len == sizeof(buf)) + { + Emotion_Xine_Video *ev; + + fr = buf; + ev = _emotion_video_get(fr->obj); + if (ev) + { + em_frame_done(ev); + ev->cur_frame = fr; + _em_get_pos_len(ev); + if ((xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_VIDEO)) && + (xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_HANDLED))) + { + if (ev->video_mute) em_frame_done(ev); + else _emotion_frame_new(fr->obj); + } + _emotion_frame_resize(fr->obj, fr->w, fr->h, fr->ratio); + _emotion_video_pos_update(fr->obj, ev->pos, ev->len); + } + } + } + return EINA_TRUE; + data = NULL; +} + +static void +_em_event(void *data, const xine_event_t *event) +{ + void *buf[2]; + Emotion_Xine_Event *new_ev; + Emotion_Xine_Video *ev; + + ev = data; + new_ev = calloc(1, sizeof(Emotion_Xine_Event)); + if (!new_ev) return; + new_ev->mtype = 0; + new_ev->type = event->type; + if (event->data) + { + new_ev->xine_event = malloc(event->data_length); + if (!new_ev->xine_event) + { + free(new_ev); + return; + } + memcpy(new_ev->xine_event, event->data, event->data_length); + } + buf[0] = data; + buf[1] = new_ev; + if (write(ev->fd_ev_write, buf, sizeof(buf)) < 0) perror("write"); +} + +static void +_em_module_event(void *data, int type) +{ + void *buf[2]; + Emotion_Xine_Event *new_ev; + Emotion_Xine_Video *ev; + + ev = data; + new_ev = calloc(1, sizeof(Emotion_Xine_Event)); + if (!new_ev) return; + new_ev->mtype = type; + new_ev->type = -1; + buf[0] = data; + buf[1] = new_ev; + if (write(ev->fd_ev_write, buf, sizeof(buf)) < 0) perror("write"); +} + +static Eina_Bool +_em_audio_only_poller(void *data) +{ + Emotion_Xine_Video *ev; + + ev = data; + _em_get_pos_len(ev); + return EINA_TRUE; +} + +static Eina_Bool +_em_fd_ev_active(void *data __UNUSED__, Ecore_Fd_Handler *fdh) +{ + int fd, len; + void *buf[2]; + + fd = ecore_main_fd_handler_fd_get(fdh); + while ((len = read(fd, buf, sizeof(buf))) > 0) + { + if (len == sizeof(buf)) + { + Emotion_Xine_Video *ev; + Emotion_Xine_Event *eev; + + ev = buf[0]; + eev = buf[1]; + if (eev->mtype != 0) + { + switch (eev->mtype) + { + case 1: /* init done */ + ev->play_ok = 1; + break; + case 2: /* open done */ + ev->play_ok = 1; + if (ev->anim) + { + ecore_animator_del(ev->anim); + ev->anim = NULL; + } + _emotion_open_done(ev->obj); + _emotion_frame_resize(ev->obj, ev->w, ev->h, ev->ratio); + break; + case 3: /* shutdown done */ + if (ev->anim) + { + ecore_animator_del(ev->anim); + ev->anim = NULL; + } + ev->play_ok = 1; + break; + case 4: /* play done */ + ev->play_ok = 1; + if (ev->anim) + { + ecore_animator_del(ev->anim); + ev->anim = NULL; + } + if ((!(xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_VIDEO) && + xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_HANDLED))) && + (xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_AUDIO) && + xine_get_stream_info(ev->stream, XINE_STREAM_INFO_AUDIO_HANDLED))) + ev->anim = ecore_animator_add(_em_audio_only_poller, ev); + _emotion_playback_started(ev->obj); + break; + case 5: /* stop done */ + if (ev->anim) + { + ecore_animator_del(ev->anim); + ev->anim = NULL; + } + ev->play_ok = 1; + break; + case 6: /* seek done */ + ev->play_ok = 1; + _emotion_seek_done(ev->obj); + _em_get_pos_len(ev); + _emotion_video_pos_update(ev->obj, ev->pos, ev->len); + break; + case 7: /* eject done */ + if (ev->anim) + { + ecore_animator_del(ev->anim); + ev->anim = NULL; + } + ev->play_ok = 1; + break; + case 8: /* spu mute done */ + ev->play_ok = 1; + break; + case 9: /* channel done */ + ev->play_ok = 1; + break; + case 10: /* volume done */ + ev->play_ok = 1; + break; + case 11: /* close done */ + if (ev->anim) + { + ecore_animator_del(ev->anim); + ev->anim = NULL; + } + ev->play_ok = 1; + break; + case 15: /* get pos done */ + if (ev->last_pos != ev->pos) + { + ev->last_pos = ev->pos; + _emotion_video_pos_update(ev->obj, ev->pos, ev->len); + } + break; + default: + break; + } + } + else + { + switch (eev->type) + { + case XINE_EVENT_UI_PLAYBACK_FINISHED: + { + ev->play = 0; + _emotion_decode_stop(ev->obj); + _emotion_playback_finished(ev->obj); + } + break; + case XINE_EVENT_UI_CHANNELS_CHANGED: + { + _emotion_channels_change(ev->obj); + } + break; + case XINE_EVENT_UI_SET_TITLE: + { + xine_ui_data_t *e; + + e = (xine_ui_data_t *)eev->xine_event; + _emotion_title_set(ev->obj, e->str); + } + break; + case XINE_EVENT_FRAME_FORMAT_CHANGE: + break; + case XINE_EVENT_UI_MESSAGE: + { + WRN("UI Message [FIXME: break this out to emotion api]"); + // e->type = error type(XINE_MSG_NO_ERROR, XINE_MSG_GENERAL_WARNING, XINE_MSG_UNKNOWN_HOST etc.) + // e->messages is a list of messages DOUBLE null terminated + } + break; + case XINE_EVENT_AUDIO_LEVEL: + { + _emotion_audio_level_change(ev->obj); + WRN("Audio Level [FIXME: break this out to emotion api]"); + // e->left (0->100) + // e->right + // e->mute + } + break; + case XINE_EVENT_PROGRESS: + { + xine_progress_data_t *e; + + e = (xine_progress_data_t *)eev->xine_event; + DBG("PROGRESS: %i", e->percent); + ev->buffer = e->percent; + _emotion_progress_set(ev->obj, (char *)e->description, (double)e->percent / 100.0); + } + break; + case XINE_EVENT_MRL_REFERENCE_EXT: + { + xine_mrl_reference_data_ext_t *e; + + e = (xine_mrl_reference_data_ext_t *)eev->xine_event; + _emotion_file_ref_set(ev->obj, e->mrl, e->alternative); + } + break; + case XINE_EVENT_UI_NUM_BUTTONS: + { + xine_ui_data_t *e; + + e = (xine_ui_data_t *)eev->xine_event; + _emotion_spu_button_num_set(ev->obj, e->num_buttons); + } + break; + case XINE_EVENT_SPU_BUTTON: + { + xine_spu_button_t *e; + + e = (xine_spu_button_t *)eev->xine_event; + if (e->direction == 1) + _emotion_spu_button_set(ev->obj, e->button); + else + _emotion_spu_button_set(ev->obj, -1); + } + break; + case XINE_EVENT_DROPPED_FRAMES: + { + xine_dropped_frames_t *e; + + e = (xine_dropped_frames_t *)eev->xine_event; + WRN("Dropped Frames (skipped %i) (discarded %i) [FIXME: break this out to the emotion api]", e->skipped_frames, e->discarded_frames); + // e->skipped_frames = % frames skipped * 10 + // e->discarded_frames = % frames skipped * 10 + } + break; + default: + // DBG("unknown event type %i", eev->type); + break; + } + } + if (eev->xine_event) free(eev->xine_event); + free(eev); + } + } + return EINA_TRUE; +} + +static void * +_em_get_pos_len_th(void *par) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)par; + + for (;;) + { + pthread_mutex_lock(&(ev->get_pos_len_mutex)); + pthread_cond_wait(&(ev->get_pos_len_cond), &(ev->get_pos_len_mutex)); + pthread_mutex_unlock(&(ev->get_pos_len_mutex)); + if (ev->get_poslen) + { + int pos_stream = 0; + int pos_time = 0; + int length_time = 0; + + if (xine_get_pos_length(ev->stream, &pos_stream, &pos_time, &length_time)) + { + if (length_time == 0) + { + ev->pos = (double)pos_stream / 65535; + ev->len = 1.0; + ev->no_time = 1; + } + else + { + ev->pos = (double)pos_time / 1000.0; + ev->len = (double)length_time / 1000.0; + ev->no_time = 0; + } + } + ev->get_poslen = 0; + _em_module_event(ev, 15); /* event - getpos done */ + //DBG("get pos %3.3f", ev->pos); + } + if (ev->delete_me) + { + ev->get_pos_thread_deleted = 1; + return NULL; + } + } + return NULL; +} + +static void +_em_get_pos_len(Emotion_Xine_Video *ev) +{ + if (!ev->play_ok) return; + ev->get_poslen = 1; + pthread_mutex_lock(&(ev->get_pos_len_mutex)); + pthread_cond_broadcast(&(ev->get_pos_len_cond)); + pthread_mutex_unlock(&(ev->get_pos_len_mutex)); +} + +static Emotion_Video_Module em_module = +{ + em_init, /* init */ + em_shutdown, /* shutdown */ + em_file_open, /* file_open */ + em_file_close, /* file_close */ + em_play, /* play */ + em_stop, /* stop */ + em_size_get, /* size_get */ + em_pos_set, /* pos_set */ + em_len_get, /* len_get */ + em_buffer_size_get, /* buffer_size_get */ + em_fps_num_get, /* fps_num_get */ + em_fps_den_get, /* fps_den_get */ + em_fps_get, /* fps_get */ + em_pos_get, /* pos_get */ + em_vis_set, /* vis_set */ + em_vis_get, /* vis_get */ + em_vis_supported, /* vis_supported */ + em_ratio_get, /* ratio_get */ + em_video_handled, /* video_handled */ + em_audio_handled, /* audio_handled */ + em_seekable, /* seekable */ + em_frame_done, /* frame_done */ + em_format_get, /* format_get */ + em_video_data_size_get, /* video_data_size_get */ + em_yuv_rows_get, /* yuv_rows_get */ + em_bgra_data_get, /* bgra_data_get */ + em_event_feed, /* event_feed */ + em_event_mouse_button_feed, /* event_mouse_button_feed */ + em_event_mouse_move_feed, /* event_mouse_move_feed */ + em_video_channel_count, /* video_channel_count */ + em_video_channel_set, /* video_channel_set */ + em_video_channel_get, /* video_channel_get */ + em_video_channel_name_get, /* video_channel_name_get */ + em_video_channel_mute_set, /* video_channel_mute_set */ + em_video_channel_mute_get, /* video_channel_mute_get */ + em_audio_channel_count, /* audio_channel_count */ + em_audio_channel_set, /* audio_channel_set */ + em_audio_channel_get, /* audio_channel_get */ + em_audio_channel_name_get, /* audio_channel_name_get */ + em_audio_channel_mute_set, /* audio_channel_mute_set */ + em_audio_channel_mute_get, /* audio_channel_mute_get */ + em_audio_channel_volume_set, /* audio_channel_volume_set */ + em_audio_channel_volume_get, /* audio_channel_volume_get */ + em_spu_channel_count, /* spu_channel_count */ + em_spu_channel_set, /* spu_channel_set */ + em_spu_channel_get, /* spu_channel_get */ + em_spu_channel_name_get, /* spu_channel_name_get */ + em_spu_channel_mute_set, /* spu_channel_mute_set */ + em_spu_channel_mute_get, /* spu_channel_mute_get */ + em_chapter_count, /* chapter_count */ + em_chapter_set, /* chapter_set */ + em_chapter_get, /* chapter_get */ + em_chapter_name_get, /* chapter_name_get */ + em_speed_set, /* speed_set */ + em_speed_get, /* speed_get */ + em_eject, /* eject */ + em_meta_get, /* meta_get */ + NULL, /* priority_set */ + NULL, /* priority_get */ + NULL /* handle */ +}; + +static Eina_Bool +module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt) +{ + if (!module) + return EINA_FALSE; + + if (_emotion_xine_log_domain < 0) + { + eina_threads_init(); + eina_log_threads_enable(); + _emotion_xine_log_domain = eina_log_domain_register + ("emotion-xine", EINA_COLOR_LIGHTCYAN); + if (_emotion_xine_log_domain < 0) + { + EINA_LOG_CRIT("Could not register log domain 'emotion-xine'"); + return EINA_FALSE; + } + } + + if (!em_module.init(obj, video, opt)) + return EINA_FALSE; + + *module = &em_module; + return EINA_TRUE; +} + +static void +module_close(Emotion_Video_Module *module __UNUSED__, void *video) +{ + em_module.shutdown(video); +} + +Eina_Bool +xine_module_init(void) +{ + return _emotion_module_register("xine", module_open, module_close); +} + +void +xine_module_shutdown(void) +{ + _emotion_module_unregister("xine"); +} + +#ifndef EMOTION_STATIC_BUILD_XINE + +EINA_MODULE_INIT(xine_module_init); +EINA_MODULE_SHUTDOWN(xine_module_shutdown); + +#endif + +#if 0 +void +em_debug(Emotion_Xine_Video *ev) +{ + int has_chapters = 0; + int max_spu = 0; + int max_audio = 0; + int video_channels = 0; + int video_streams = 0; + int video_seekable = 0; + char *title; + char *comment; + char *artist; + char *genre; + char *album; + char *year; + char *cdindex_discid; + int video_channel = 0; + int audio_channel = 0; + int spu_channel = 0; + int video_ratio = 0; + int audio_mode = 0; + +// return; + has_chapters = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_CHAPTERS); + max_spu = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL); + max_audio = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL); + video_channels = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_CHANNELS); + video_streams = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_STREAMS); + video_seekable = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_SEEKABLE); + title = xine_get_meta_info(ev->stream, XINE_META_INFO_TITLE); + comment = xine_get_meta_info(ev->stream, XINE_META_INFO_COMMENT); + artist = xine_get_meta_info(ev->stream, XINE_META_INFO_ARTIST); + genre = xine_get_meta_info(ev->stream, XINE_META_INFO_GENRE); + album = xine_get_meta_info(ev->stream, XINE_META_INFO_ALBUM); + year = xine_get_meta_info(ev->stream, XINE_META_INFO_YEAR); + cdindex_discid = xine_get_meta_info(ev->stream, XINE_META_INFO_CDINDEX_DISCID); + video_channel = xine_get_param(ev->stream, XINE_PARAM_VIDEO_CHANNEL); + audio_channel = xine_get_param(ev->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL); + spu_channel = xine_get_param(ev->stream, XINE_PARAM_SPU_CHANNEL); + video_ratio = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_RATIO); + audio_mode = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_AUDIO_MODE); + DBG("has_chapters = %i", has_chapters); + DBG("max_spu = %i", max_spu); + DBG("max_audio = %i", max_audio); + DBG("video_channels = %i", video_channels); + DBG("video_streams = %i", video_streams); + DBG("video_seekable = %i", video_seekable); + DBG("title = %s", title); + DBG("comment = %s", comment); + DBG("artist = %s", artist); + DBG("genre = %s", genre); + DBG("album = %s", album); + DBG("year = %s", year); + DBG("cdindex_discid = %s", cdindex_discid); + DBG("video_channel = %i", video_channel); + DBG("audio_channel = %i", audio_channel); + DBG("spu_channels = %i", spu_channel); + DBG("video_ratio = %i", video_ratio); + DBG("audio_mode = %i", audio_mode); + { + int i; + + for (i = 0; i <= max_audio; i++) + { + char lang[XINE_LANG_MAX + 1]; + char buf[128] = "NONE"; + + lang[0] = 0; + if (xine_get_audio_lang(ev->stream, i, lang)) + eina_strlcpy(buf, lang, sizeof(buf)); + DBG(" AUDIO %i = %s", i, buf); + } + for (i = 0; i <= max_spu; i++) + { + char lang[XINE_LANG_MAX + 1]; + char buf[128] = "NONE"; + + lang[0] = 0; + if (xine_get_spu_lang(ev->stream, i, lang)) + eina_strlcpy(buf, lang, sizeof(buf)); + DBG(" SPU %i = %s", i, buf); + } + } +} +#endif diff --git a/src/modules/xine/emotion_xine.h b/src/modules/xine/emotion_xine.h new file mode 100644 index 0000000..c1cae2e --- /dev/null +++ b/src/modules/xine/emotion_xine.h @@ -0,0 +1,98 @@ +#ifndef EMOTION_XINE_H +#define EMOTION_XINE_H + +#include +#include +#include +#include +#include + +typedef struct _Emotion_Xine_Video Emotion_Xine_Video; +typedef struct _Emotion_Xine_Video_Frame Emotion_Xine_Video_Frame; +typedef struct _Emotion_Xine_Event Emotion_Xine_Event; + +struct _Emotion_Xine_Video +{ + xine_t *decoder; + xine_video_port_t *video; + xine_audio_port_t *audio; + xine_stream_t *stream; + xine_event_queue_t *queue; + volatile double len; + volatile double pos; + volatile double last_pos; + volatile double volume; + volatile double buffer; + double fps; + double ratio; + int w, h; + Evas_Object *obj; + volatile Emotion_Xine_Video_Frame *cur_frame; + volatile int get_poslen; + volatile int spu_channel; + volatile int audio_channel; + volatile int video_channel; + volatile int fq; + Emotion_Vis vis; + int fd_read; + int fd_write; + Ecore_Fd_Handler *fd_handler; + int fd_ev_read; + int fd_ev_write; + Ecore_Fd_Handler *fd_ev_handler; + Ecore_Animator *anim; + unsigned char play : 1; + unsigned char just_loaded : 1; + unsigned char video_mute : 1; + unsigned char audio_mute : 1; + unsigned char spu_mute : 1; + Eina_Bool opt_no_video : 1; + Eina_Bool opt_no_audio : 1; + volatile unsigned char delete_me : 1; + volatile unsigned char no_time : 1; + volatile unsigned char opening : 1; + volatile unsigned char closing : 1; + volatile unsigned char have_vo : 1; + volatile unsigned char play_ok : 1; + + pthread_t get_pos_len_th; + pthread_cond_t get_pos_len_cond; + pthread_mutex_t get_pos_len_mutex; + + pthread_t slave_th; + int fd_slave_read; + int fd_slave_write; + + unsigned char get_pos_thread_deleted : 1; +}; + +struct _Emotion_Xine_Video_Frame +{ + int w, h; + double ratio; + Emotion_Format format; + unsigned char *y, *u, *v; + unsigned char *bgra_data; + int y_stride, u_stride, v_stride; + Evas_Object *obj; + double timestamp; + void (*done_func)(void *data); + void *done_data; + void *frame; +}; + +struct _Emotion_Xine_Event +{ + int type; + void *xine_event; + int mtype; +}; + +extern int _emotion_xine_log_domain; +#define DBG(...) EINA_LOG_DOM_DBG(_emotion_xine_log_domain, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(_emotion_xine_log_domain, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(_emotion_xine_log_domain, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(_emotion_xine_log_domain, __VA_ARGS__) +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_emotion_xine_log_domain, __VA_ARGS__) + +#endif diff --git a/src/modules/xine/emotion_xine_vo_out.c b/src/modules/xine/emotion_xine_vo_out.c new file mode 100644 index 0000000..3ae8e1c --- /dev/null +++ b/src/modules/xine/emotion_xine_vo_out.c @@ -0,0 +1,766 @@ +/***************************************************************************/ +/*** emotion xine display engine ***/ +/***************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#include "Emotion.h" +#include "emotion_private.h" +#include "emotion_xine.h" + +#include +#include +#include +#include +#include + +#define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf) + +/***************************************************************************/ +typedef struct _Emotion_Frame Emotion_Frame; +typedef struct _Emotion_Driver Emotion_Driver; +typedef struct _Emotion_Class Emotion_Class; +typedef struct _Emotion_Lut Emotion_Lut; + +struct _Emotion_Frame +{ + vo_frame_t vo_frame; + int width; + int height; + double ratio; + int format; + xine_t *xine; + + Emotion_Xine_Video_Frame frame; + unsigned char in_use : 1; +}; + +struct _Emotion_Driver +{ + vo_driver_t vo_driver; + config_values_t *config; + int ratio; + xine_t *xine; + Emotion_Xine_Video *ev; +}; + +struct _Emotion_Class +{ + video_driver_class_t driver_class; + config_values_t *config; + xine_t *xine; +}; + +struct _Emotion_Lut +{ + uint8_t cb : 8; + uint8_t cr : 8; + uint8_t y : 8; + uint8_t foo : 8; +} __attribute__ ((packed)); + +typedef void (*done_func_type)(void *data); + +/***************************************************************************/ +static void *_emotion_class_init (xine_t *xine, void *visual); +static void _emotion_class_dispose (video_driver_class_t *driver_class); +static char *_emotion_class_identifier_get (video_driver_class_t *driver_class); +static char *_emotion_class_description_get (video_driver_class_t *driver_class); + +static vo_driver_t *_emotion_open (video_driver_class_t *driver_class, const void *visual); +static void _emotion_dispose (vo_driver_t *vo_driver); + +static int _emotion_redraw (vo_driver_t *vo_driver); + +static uint32_t _emotion_capabilities_get (vo_driver_t *vo_driver); +static int _emotion_gui_data_exchange (vo_driver_t *vo_driver, int data_type, void *data); + +static int _emotion_property_set (vo_driver_t *vo_driver, int property, int value); +static int _emotion_property_get (vo_driver_t *vo_driver, int property); +static void _emotion_property_min_max_get (vo_driver_t *vo_driver, int property, int *min, int *max); + +static vo_frame_t *_emotion_frame_alloc (vo_driver_t *vo_driver); +static void _emotion_frame_dispose (vo_frame_t *vo_frame); +static void _emotion_frame_format_update (vo_driver_t *vo_driver, vo_frame_t *vo_frame, uint32_t width, uint32_t height, double ratio, int format, int flags); +static void _emotion_frame_display (vo_driver_t *vo_driver, vo_frame_t *vo_frame); +static void _emotion_frame_field (vo_frame_t *vo_frame, int which_field); + +static void _emotion_frame_data_free (Emotion_Frame *fr); +static void _emotion_frame_data_unlock (Emotion_Frame *fr); + +static void _emotion_overlay_begin (vo_driver_t *vo_driver, vo_frame_t *vo_frame, int changed); +static void _emotion_overlay_end (vo_driver_t *vo_driver, vo_frame_t *vo_frame); +static void _emotion_overlay_blend (vo_driver_t *vo_driver, vo_frame_t *vo_frame, vo_overlay_t *vo_overlay); + +static void _emotion_overlay_mem_blend_8 (uint8_t *mem, uint8_t val, uint8_t o, size_t sz); +static void _emotion_overlay_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, int dst_width, int dst_height, int dst_pitches[3]); + +static void _emotion_yuy2_to_bgra32 (int width, int height, unsigned char *src, unsigned char *dst); + +/***************************************************************************/ +static vo_info_t _emotion_info = +{ + 1, /* priority */ + XINE_VISUAL_TYPE_NONE /* visual type */ +}; + +plugin_info_t emotion_xine_plugin_info[] = +{ + { PLUGIN_VIDEO_OUT, 21, "emotion", XINE_VERSION_CODE, &_emotion_info, _emotion_class_init }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; + +/***************************************************************************/ +static void * +_emotion_class_init(xine_t *xine, void *visual __UNUSED__) +{ + Emotion_Class *cl; + +// DBG(""); + cl = (Emotion_Class *) malloc(sizeof(Emotion_Class)); + if (!cl) return NULL; + cl->driver_class.open_plugin = _emotion_open; +#if XINE_MAJOR_VERSION < 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION < 2) + cl->driver_class.get_identifier = _emotion_class_identifier_get; + cl->driver_class.get_description = _emotion_class_description_get; +#else + cl->driver_class.identifier = _emotion_class_identifier_get(NULL); + cl->driver_class.description = _emotion_class_description_get(NULL); +#endif + cl->driver_class.dispose = _emotion_class_dispose; + cl->config = xine->config; + cl->xine = xine; + + return cl; +} + +static void +_emotion_class_dispose(video_driver_class_t *driver_class) +{ + Emotion_Class *cl; + + cl = (Emotion_Class *)driver_class; + free(cl); +} + +static char * +_emotion_class_identifier_get(video_driver_class_t *driver_class __UNUSED__) +{ + return "emotion"; +} + +static char * +_emotion_class_description_get(video_driver_class_t *driver_class __UNUSED__) +{ + return "Emotion xine video output plugin"; +} + +/***************************************************************************/ +static vo_driver_t * +_emotion_open(video_driver_class_t *driver_class, const void *visual) +{ + Emotion_Class *cl; + Emotion_Driver *dv; + + cl = (Emotion_Class *)driver_class; + /* visual here is the data ptr passed to xine_open_video_driver() */ +// DBG(""); + dv = (Emotion_Driver *)malloc(sizeof(Emotion_Driver)); + if (!dv) return NULL; + + dv->config = cl->config; + dv->xine = cl->xine; + dv->ratio = XINE_VO_ASPECT_AUTO; + dv->vo_driver.get_capabilities = _emotion_capabilities_get; + dv->vo_driver.alloc_frame = _emotion_frame_alloc; + dv->vo_driver.update_frame_format = _emotion_frame_format_update; + dv->vo_driver.overlay_begin = _emotion_overlay_begin; + dv->vo_driver.overlay_blend = _emotion_overlay_blend; + dv->vo_driver.overlay_end = _emotion_overlay_end; + dv->vo_driver.display_frame = _emotion_frame_display; + dv->vo_driver.get_property = _emotion_property_get; + dv->vo_driver.set_property = _emotion_property_set; + dv->vo_driver.get_property_min_max = _emotion_property_min_max_get; + dv->vo_driver.gui_data_exchange = _emotion_gui_data_exchange; + dv->vo_driver.dispose = _emotion_dispose; + dv->vo_driver.redraw_needed = _emotion_redraw; + dv->ev = (Emotion_Xine_Video *)visual; + dv->ev->have_vo = 1; + DBG("vo_driver = %p", &dv->vo_driver); + return &dv->vo_driver; +} + +static void +_emotion_dispose(vo_driver_t *vo_driver) +{ + Emotion_Driver *dv; + + dv = (Emotion_Driver *)vo_driver; + dv->ev->have_vo = 0; + DBG("vo_driver = %p", dv); + free(dv); +} + +/***************************************************************************/ +static int +_emotion_redraw(vo_driver_t *vo_driver __UNUSED__) +{ +// DBG(""); + return 0; +} + +/***************************************************************************/ +static uint32_t +_emotion_capabilities_get(vo_driver_t *vo_driver __UNUSED__) +{ +// DBG(""); + return VO_CAP_YV12 | VO_CAP_YUY2; +} + +/***************************************************************************/ +static int +_emotion_gui_data_exchange(vo_driver_t *vo_driver __UNUSED__, int data_type, void *data __UNUSED__) +{ +// DBG(""); + switch (data_type) + { + case XINE_GUI_SEND_COMPLETION_EVENT: + break; + case XINE_GUI_SEND_DRAWABLE_CHANGED: + break; + case XINE_GUI_SEND_EXPOSE_EVENT: + break; + case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: + break; + case XINE_GUI_SEND_VIDEOWIN_VISIBLE: + break; + case XINE_GUI_SEND_SELECT_VISUAL: + break; + default: + break; + } + return 0; +} + +/***************************************************************************/ +static int +_emotion_property_set(vo_driver_t *vo_driver, int property, int value) +{ + Emotion_Driver *dv; + + dv = (Emotion_Driver *)vo_driver; +// DBG(""); + switch (property) + { + case VO_PROP_ASPECT_RATIO: + if (value >= XINE_VO_ASPECT_NUM_RATIOS) + value = XINE_VO_ASPECT_AUTO; +// DBG("DRIVER RATIO SET %i!", value); + dv->ratio = value; + break; + default: + break; + } + return value; +} + +static int +_emotion_property_get(vo_driver_t *vo_driver, int property) +{ + Emotion_Driver *dv; + + dv = (Emotion_Driver *)vo_driver; +// DBG(""); + switch (property) + { + case VO_PROP_ASPECT_RATIO: + return dv->ratio; + break; + default: + break; + } + return 0; +} + +static void +_emotion_property_min_max_get(vo_driver_t *vo_driver __UNUSED__, int property __UNUSED__, int *min, int *max) +{ +// DBG(""); + *min = 0; + *max = 0; +} + +/***************************************************************************/ +static vo_frame_t * +_emotion_frame_alloc(vo_driver_t *vo_driver __UNUSED__) +{ + Emotion_Frame *fr; + +// DBG(""); + fr = (Emotion_Frame *)calloc(1, sizeof(Emotion_Frame)); + if (!fr) return NULL; + + fr->vo_frame.base[0] = NULL; + fr->vo_frame.base[1] = NULL; + fr->vo_frame.base[2] = NULL; + + fr->vo_frame.proc_slice = NULL; + fr->vo_frame.proc_frame = NULL; + fr->vo_frame.field = _emotion_frame_field; + fr->vo_frame.dispose = _emotion_frame_dispose; + fr->vo_frame.driver = vo_driver; + + return (vo_frame_t *)fr; +} + +static void +_emotion_frame_dispose(vo_frame_t *vo_frame) +{ + Emotion_Frame *fr; + + fr = (Emotion_Frame *)vo_frame; +// DBG(""); + _emotion_frame_data_free(fr); + free(fr); +} + +static void +_emotion_frame_format_update(vo_driver_t *vo_driver, vo_frame_t *vo_frame, uint32_t width, uint32_t height, double ratio, int format, int flags __UNUSED__) +{ + Emotion_Driver *dv; + Emotion_Frame *fr; + + dv = (Emotion_Driver *)vo_driver; + fr = (Emotion_Frame *)vo_frame; + + if ((fr->width != (int)width) || (fr->height != (int)height) || + (fr->format != format) || (!fr->vo_frame.base[0])) + { +// DBG(""); + _emotion_frame_data_free(fr); + + fr->width = width; + fr->height = height; + fr->format = format; + + switch (format) + { + case XINE_IMGFMT_YV12: + { + int y_size, uv_size; + + fr->frame.format = EMOTION_FORMAT_YV12; + fr->vo_frame.pitches[0] = 8 * ((width + 7) / 8); + fr->vo_frame.pitches[1] = 8 * ((width + 15) / 16); + fr->vo_frame.pitches[2] = 8 * ((width + 15) / 16); + + y_size = fr->vo_frame.pitches[0] * height; + uv_size = fr->vo_frame.pitches[1] * ((height + 1) / 2); + + fr->vo_frame.base[0] = malloc(y_size + (2 * uv_size)); + fr->vo_frame.base[1] = fr->vo_frame.base[0] + y_size + uv_size; + fr->vo_frame.base[2] = fr->vo_frame.base[0] + y_size; + fr->frame.w = fr->width; + fr->frame.h = fr->height; + fr->frame.ratio = fr->vo_frame.ratio; + fr->frame.y = fr->vo_frame.base[0]; + fr->frame.u = fr->vo_frame.base[1]; + fr->frame.v = fr->vo_frame.base[2]; + fr->frame.bgra_data = NULL; + fr->frame.y_stride = fr->vo_frame.pitches[0]; + fr->frame.u_stride = fr->vo_frame.pitches[1]; + fr->frame.v_stride = fr->vo_frame.pitches[2]; + fr->frame.obj = dv->ev->obj; + } + break; + case XINE_IMGFMT_YUY2: + { + fr->frame.format = EMOTION_FORMAT_BGRA; + fr->vo_frame.pitches[0] = 8 * ((width + 3) / 4); + fr->vo_frame.pitches[1] = 0; + fr->vo_frame.pitches[2] = 0; + + fr->vo_frame.base[0] = malloc(fr->vo_frame.pitches[0] * height); + fr->vo_frame.base[1] = NULL; + fr->vo_frame.base[2] = NULL; + + fr->frame.w = fr->width; + fr->frame.h = fr->height; + fr->frame.ratio = fr->vo_frame.ratio; + fr->frame.y = NULL; + fr->frame.u = NULL; + fr->frame.v = NULL; + fr->frame.bgra_data = malloc(fr->width * fr->height * 4); + fr->frame.y_stride = 0; + fr->frame.u_stride = 0; + fr->frame.v_stride = 0; + fr->frame.obj = dv->ev->obj; + } + break; + default: + break; + } + if (((format == XINE_IMGFMT_YV12) + && ((!fr->vo_frame.base[0]) + || (!fr->vo_frame.base[1]) + || (!fr->vo_frame.base[2]))) + || ((format == XINE_IMGFMT_YUY2) + && ((!fr->vo_frame.base[0]) + || (!fr->frame.bgra_data)))) + { + _emotion_frame_data_free(fr); + } + } + fr->frame.ratio = fr->vo_frame.ratio; + fr->ratio = ratio; +} + +static void +_emotion_frame_display(vo_driver_t *vo_driver, vo_frame_t *vo_frame) +{ + Emotion_Driver *dv; + Emotion_Frame *fr; + + dv = (Emotion_Driver *)vo_driver; + fr = (Emotion_Frame *)vo_frame; +// DBG("fq %i %p", dv->ev->fq, dv->ev); +// if my frame queue is too deep ( > 4 frames) simply block and wait for them +// to drain +// while (dv->ev->fq > 4) usleep(1); + if (dv->ev) + { + void *buf; + + if (dv->ev->closing) return; + if (fr->format == XINE_IMGFMT_YUY2) + { + _emotion_yuy2_to_bgra32(fr->width, fr->height, fr->vo_frame.base[0], fr->frame.bgra_data); + } + + buf = &(fr->frame); + fr->frame.timestamp = (double)fr->vo_frame.vpts / 90000.0; + fr->frame.done_func = (done_func_type)_emotion_frame_data_unlock; + fr->frame.done_data = fr; +// DBG("FRAME FOR %p", dv->ev); + if (write(dv->ev->fd_write, &buf, sizeof(void *)) < 0) perror("write"); +// DBG("-- FRAME DEC %p == %i", fr->frame.obj, ret); + fr->in_use = 1; + dv->ev->fq++; + } + /* hmm - must find a way to sanely copy data out... FIXME problem */ +// fr->vo_frame.free(&fr->vo_frame); +} + +static void +_emotion_frame_field(vo_frame_t *vo_frame __UNUSED__, int which_field __UNUSED__) +{ +// DBG(""); +} + +/***************************************************************************/ +static void +_emotion_frame_data_free(Emotion_Frame *fr) +{ + if (fr->vo_frame.base[0]) + { + free(fr->vo_frame.base[0]); + fr->vo_frame.base[0] = NULL; + fr->vo_frame.base[1] = NULL; + fr->vo_frame.base[2] = NULL; + fr->frame.y = fr->vo_frame.base[0]; + fr->frame.u = fr->vo_frame.base[1]; + fr->frame.v = fr->vo_frame.base[2]; + } + if (fr->frame.bgra_data) + { + free(fr->frame.bgra_data); + fr->frame.bgra_data = NULL; + } +} + +static void +_emotion_frame_data_unlock(Emotion_Frame *fr) +{ +// DBG(""); + if (fr->in_use) + { + fr->vo_frame.free(&fr->vo_frame); + fr->in_use = 0; + } +} + +/***************************************************************************/ +static void +_emotion_overlay_begin(vo_driver_t *vo_driver __UNUSED__, vo_frame_t *vo_frame __UNUSED__, int changed __UNUSED__) +{ +// DBG(""); +} + +static void +_emotion_overlay_end(vo_driver_t *vo_driver __UNUSED__, vo_frame_t *vo_frame __UNUSED__) +{ +// DBG(""); +} + +static void +_emotion_overlay_blend(vo_driver_t *vo_driver __UNUSED__, vo_frame_t *vo_frame, vo_overlay_t *vo_overlay __UNUSED__) +{ + Emotion_Frame *fr; + + fr = (Emotion_Frame *)vo_frame; +// DBG(""); + _emotion_overlay_blend_yuv(fr->vo_frame.base, vo_overlay, + fr->width, fr->height, + fr->vo_frame.pitches); +} + +static void _emotion_overlay_mem_blend_8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz) +{ + uint8_t *limit = mem + sz; + while (mem < limit) + { + *mem = BLEND_BYTE(*mem, val, o); + mem++; + } +} + +static void _emotion_overlay_blend_yuv(uint8_t *dst_base[3], vo_overlay_t * img_overl, int dst_width, int dst_height, int dst_pitches[3]) +{ + Emotion_Lut *my_clut; + uint8_t *my_trans; + int src_width; + int src_height; + rle_elem_t *rle; + rle_elem_t *rle_limit; + int x_off; + int y_off; + int ymask, xmask; + int rle_this_bite; + int rle_remainder; + int rlelen; + int x, y; + int hili_right; + uint8_t clr = 0; + + src_width = img_overl->width; + src_height = img_overl->height; + rle = img_overl->rle; + rle_limit = rle + img_overl->num_rle; + x_off = img_overl->x; + y_off = img_overl->y; + + if (!rle) return; + + uint8_t *dst_y = dst_base[0] + dst_pitches[0] * y_off + x_off; + uint8_t *dst_cr = dst_base[2] + (y_off / 2) * dst_pitches[1] + (x_off / 2) + 1; + uint8_t *dst_cb = dst_base[1] + (y_off / 2) * dst_pitches[2] + (x_off / 2) + 1; + my_clut = (Emotion_Lut *) img_overl->hili_color; + my_trans = img_overl->hili_trans; + + /* avoid wraping overlay if drawing to small image */ + if( (x_off + img_overl->hili_right) < dst_width ) + hili_right = img_overl->hili_right; + else + hili_right = dst_width - 1 - x_off; + + /* avoid buffer overflow */ + if( (src_height + y_off) >= dst_height ) + src_height = dst_height - 1 - y_off; + + rlelen=rle_remainder=0; + for (y = 0; y < src_height; y++) + { + ymask = ((img_overl->hili_top > y) || (img_overl->hili_bottom < y)); + xmask = 0; + + for (x = 0; x < src_width;) + { + uint16_t o; + + if (rlelen == 0) + { + rle_remainder = rlelen = rle->len; + clr = rle->color; + rle++; + } + if (rle_remainder == 0) + { + rle_remainder = rlelen; + } + if ((rle_remainder + x) > src_width) + { + /* Do something for long rlelengths */ + rle_remainder = src_width - x; + } + + if (ymask == 0) + { + if (x <= img_overl->hili_left) + { + /* Starts outside clip area */ + if ((x + rle_remainder - 1) > img_overl->hili_left ) + { + /* Cutting needed, starts outside, ends inside */ + rle_this_bite = (img_overl->hili_left - x + 1); + rle_remainder -= rle_this_bite; + rlelen -= rle_this_bite; + my_clut = (Emotion_Lut *) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; + } + else + { + /* no cutting needed, starts outside, ends outside */ + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + my_clut = (Emotion_Lut *) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; + } + } + else if (x < hili_right) + { + /* Starts inside clip area */ + if ((x + rle_remainder) > hili_right ) + { + /* Cutting needed, starts inside, ends outside */ + rle_this_bite = (hili_right - x); + rle_remainder -= rle_this_bite; + rlelen -= rle_this_bite; + my_clut = (Emotion_Lut *) img_overl->hili_color; + my_trans = img_overl->hili_trans; + xmask++; + } + else + { + /* no cutting needed, starts inside, ends inside */ + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + my_clut = (Emotion_Lut *) img_overl->hili_color; + my_trans = img_overl->hili_trans; + xmask++; + } + } + else if (x >= hili_right) + { + /* Starts outside clip area, ends outsite clip area */ + if ((x + rle_remainder ) > src_width ) + { + /* Cutting needed, starts outside, ends at right edge */ + /* It should never reach here due to the earlier test of src_width */ + rle_this_bite = (src_width - x ); + rle_remainder -= rle_this_bite; + rlelen -= rle_this_bite; + my_clut = (Emotion_Lut *) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; + } + else + { + /* no cutting needed, starts outside, ends outside */ + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + my_clut = (Emotion_Lut *) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; + } + } + } + else + { + /* Outside clip are due to y */ + /* no cutting needed, starts outside, ends outside */ + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + my_clut = (Emotion_Lut *) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; + } + o = my_trans[clr]; + if (o) + { + if (o >= 15) + { + memset(dst_y + x, my_clut[clr].y, rle_this_bite); + if (y & 1) + { + memset(dst_cr + (x >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1); + memset(dst_cb + (x >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1); + } + } + else + { + _emotion_overlay_mem_blend_8(dst_y + x, my_clut[clr].y, o, rle_this_bite); + if (y & 1) + { + /* Blending cr and cb should use a different function, with pre -128 to each sample */ + _emotion_overlay_mem_blend_8(dst_cr + (x >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1); + _emotion_overlay_mem_blend_8(dst_cb + (x >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1); + } + } + } + x += rle_this_bite; + if (rle >= rle_limit) + { + break; + } + } + if (rle >= rle_limit) + { + break; + } + + dst_y += dst_pitches[0]; + + if (y & 1) + { + dst_cr += dst_pitches[2]; + dst_cb += dst_pitches[1]; + } + } +} + +//TODO: Really need to improve this converter! +#define LIMIT(x) ((x) > 0xff ? 0xff : ((x) < 0 ? 0 : (x))) + +static void +_emotion_yuy2_to_bgra32(int width, int height, unsigned char *src, unsigned char *dst) +{ + int i, j; + unsigned char *y, *u, *v; + + y = src; + u = src + 1; + v = src + 3; + for (i = 0; i < width; i++) + { + for (j = 0; j < height; j++) + { + *dst++ = LIMIT(1.164 * (*y - 16) + 2.018 * (*u - 128)); + *dst++ = LIMIT(1.164 * (*y - 16) - 0.813 * (*v - 128) - 0.391 * (*u - 128)); + *dst++ = LIMIT(1.164 * (*y - 16) + 1.596 * (*v - 128)); + *dst++ = 0; + + y += 2; + if (j % 2 == 1) + { + u += 4; + v += 4; + } + } + } +} -- 2.7.4