-The Rasterman (Carsten Haitzler) <raster@rasterman.com>
-doursse (Vincent Torri) <torri@maths.univ-evry.fr>
-captainigloo
+Carsten Haitzler <raster@rasterman.com>
+Vincent Torri <torri@maths.univ-evry.fr>
+Nicolas Aguirre <aguirre.nicolas@gmail.com>
+Sebastian Dransfeld <sd@tango.flipp.net>
+Cedric Bail <cedric.bail@free.fr>
+Rafael Antognolli <antognolli@profusion.mobi>
+Jérôme Pinot <ngc891@gmail.com>
+Pierre Le Magourou <pierre.lemagourou@openwide.fr>
+Hugo Camboulive <hugo.camboulive@zodiacaerospace.com>
+Sohyun Kim <anna1014.kim@samsung.com>
-Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
+Copyright notice for Emotion:
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+Copyright (C) 2004-2011 Carsten Haitzler and various contributors (see AUTHORS)
-The above copyright notice and this permission notice shall be included in
-all copies of the Software and its Copyright notices. In addition publicly
-documented acknowledgment must be given that this software has been used if no
-source code of this software is made available publicly. This includes
-acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
-documents or any documentation provided with any product containing this
-software. This License does not apply to any software that links to the
-libraries provided by this software (statically or dynamically), but only to
-the software provided.
+All rights reserved.
-Please see the COPYING.PLAIN for a plain-english explanation of this notice
-and it's intent.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 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.
-2007-10-31 Vincent Torri <doursse at users dot sf dot net>
-
- * configure.in:
- * src/bin/emotion_test_main.c:
- * src/lib/Makefile.am:
- * src/lib/emotion_private.h:
- * src/lib/emotion_smart.c:
- * src/modules/Makefile.am:
- * src/modules/emotion_gstreamer.c:
- Use ecore_plugin instead of dlfcn
- The modules names are now "xine" and "gstreamer" (it's useless to add
- the extension, as ecore_plugin does not need it).
- Look for the modules in path that is pointed by the env variable
- EMOTION_MODULES_DIR first.
- Fix a leak in the gstreamer module
- Remove some trailing spaces
- Fix bug #223
-
- add the support of URI playback. Minor fixes.
- Fix bug #114
-
-2007-09-01 Vincent Torri <doursse at users dot sf dot net>
-
- * src/modules/emotion_gstreamer.c: (em_file_open):
- * src/modules/emotion_gstreamer_pipeline.c: (cb_handoff),
- (emotion_pipeline_dvd_build), (emotion_pipeline_uri_build),
- (emotion_pipeline_file_build), (_emotion_streams_sinks_get),
- (_emotion_video_sink_fill), (_emotion_audio_sink_fill):
- * src/modules/emotion_gstreamer_pipeline.h:
- add the support of URI playback. Minor fixes.
- Fix bug #114
-
-Wed Mar 29 20:33:40 2006 Michael Jennings (mej)
-
-Xine plugins seem to no longer be built.
-----------------------------------------------------------------------
+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-05 Sohyun Kim
+
+ * Add fimcconvert element to resize and convert color using fimc on device.
+
+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-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.
+
+2012-08-30 Carsten Haitzler (The Rasterman)
+
+ 1.7.0 release
+
+2012-09-06 Sohyun Kim
+
+ * Add capsfilter to limit format and size for fimc on device.
+
+2012-10-11 Sohyun Kim
+
+ * Fix to call correct render function based on the format.
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = src data
+SUBDIRS = src data doc
-MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess emotion.spec \
- config.h.in config.sub configure install-sh \
- ltconfig ltmain.sh missing mkinstalldirs \
- stamp-h.in emotion_docs.tar emotion_docs.tar.gz \
- emotion.c acconfig.h debian/changelog depcomp
+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
-bin_SCRIPTS =
+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
-EXTRA_DIST = README AUTHORS COPYING COPYING-PLAIN \
- emotion.spec emotion.spec.in emotion.c.in gendoc Doxyfile \
- emotion.pc.in debian/changelog debian/control \
- debian/copyright debian/rules debian/libemotion0.install \
- debian/libemotion-dev.install debian/libemotion-bin.install \
- debian/libemotion-gstreamer.install debian/libemotion-xine.install
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = emotion.pc
+
+.PHONY: doc
+
+# Documentation
+
+doc:
+ @echo "entering doc/"
+ make -C doc doc
+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.
+ - Add fimcconvert and capsfilter element for device
+
+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.
+ - fix to call correct render function.
+
+Improvements:
+
+Removal:
+
-Emotion 0.0.1
+Emotion 1.7.99
+
+******************************************************************************
+
+ 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
--- /dev/null
+Before starting tests please set and export TET_ROOT_DIR variable.
+
+It's highly recommened to add similar line at the end of your
+ ~/.bashrc file:
+export TET_ROOT_DIR=/full/path/to/tetware/dir
+
+Example:
+If user with login test placed TETware in it's home directory
+(/home/test/TETware contains tetware-simulator and tetware-target)
+it should add following line to .bashrc file:
+
+export TET_ROOT_DIR=/home/test/TETware
+
+and restart terminal.
--- /dev/null
+# Customize below path information
+#TET_INSTALL_PATH=/scratchbox/TETware
+
+CURRENT_USER=`echo $HOME`
+TET_INSTALL_PATH=$CURRENT_USER/sbs/TETware
+# temporary fix for SPRC
+if [ "$TET_ROOT_DIR" != "" ]; then
+ TET_INSTALL_PATH=$TET_ROOT_DIR
+fi
+
+TET_SIMUL_PATH=$TET_INSTALL_PATH/tetware-simulator
+TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target
+TET_MOUNTED_PATH=/mnt/nfs/sbs/TETware/tetware-target
+#TET_MOUNTED_PATH=/opt/home/root/tmp/sbs/TETware/tetware-target
+
+#MACHINE=`echo $SBOX_UNAME_MACHINE`
+
+MACHINE=`echo $DEB_BUILD_ARCH_ABI`
+
+if [ $MACHINE = "gnu" ] # SBS i386
+then
+ export ARCH=simulator
+ export TET_ROOT=$TET_SIMUL_PATH
+elif [ $MACHINE = "gnueabi" ] # SBS ARM
+then
+ export ARCH=target
+ export TET_ROOT=$TET_TARGET_PATH
+else
+ export ARCH=target
+ export TET_ROOT=$TET_MOUNTED_PATH
+fi
+
+export PATH=$TET_ROOT/bin:$PATH
+export LD_LIBRARY_PATH=$TET_ROOT/lib/tet3:$LD_LIBRARY_PATH
+
+set $(pwd)
+export TET_SUITE_ROOT=$1
+
+set $(date +%y%m%d_%H%M%S)
+FILE_NAME_EXTENSION=$1
--- /dev/null
+#!/bin/bash
+
+. ./_export_env.sh # setting environment variables
+
+export TET_SUITE_ROOT=`pwd`
+FILE_NAME_EXTENSION=`date +%s`
+
+RESULT_DIR=results
+HTML_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.html
+JOURNAL_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.journal
+
+mkdir -p $RESULT_DIR
+
+echo -e "#ifndef __CONFIG_H__\n""#define __CONFIG_H__\n""#define TC_PREFIX \"`pwd`/\"\n""#endif\n" > config.h
+
+edje_cc edje/data/edje_test.edc -id edje/data/images edje/data/edje_test.edj
+
+tcc -c -p ./
+tcc -b -j $JOURNAL_RESULT -p ./
+grw -c 7 -f chtml -o $HTML_RESULT $JOURNAL_RESULT
+
+rm config.h
+
--- /dev/null
+#!/bin/sh
+
+. ./_export_env.sh # setting environment variables
+
+export TET_SUITE_ROOT=`pwd`
+RESULT_DIR=results
+
+tcc -c -p ./ # executing tcc, with clean option (-c)
+rm -r $RESULT_DIR
+rm -r tet_tmp_dir
+rm `find . -name tet_captured`
--- /dev/null
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+enum {
+ POSITIVE_TC_IDX = 0x01,
+ NEGATIVE_TC_IDX,
+ NULL_TC_IDX,
+};
+
+static void startup(void);
+static void cleanup(void);
+
+void (*tet_startup)(void) = startup;
+void (*tet_cleanup)(void) = cleanup;
+
+void sigprocess(int sig)
+{
+ signal(SIGSEGV, SIG_DFL);
+ tet_printf("[TET_SEGFAULT]:: segmentation fault in file: %s", __FILE__);
+ tet_result(TET_FAIL);
+ raise(sig);
+}
+
+static Ecore_Evas *ecore_evas;
+
+static void startup(void)
+{
+ tet_infoline("[[ TET_MSG ]]:: ============ Startup ============ ");
+ ecore_evas_init();
+ ecore_evas = ecore_evas_buffer_new(100, 45);
+}
+
+static void cleanup(void)
+{
+ tet_infoline("[[ TET_MSG ]]:: ============ Cleanup ============ ");
+ ecore_evas_shutdown();
+}
+
+static Eina_Bool
+_exit_func(void *data)
+{
+ printf("\n\nExiting main loop\n");
+ ecore_main_loop_quit();
+ return EINA_FALSE;
+}
+
+static Evas_Object *init(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ ecore_timer_add(1.0, _exit_func, NULL);
+
+ Evas *evas = ecore_evas_get(ecore_evas);
+ Evas_Object *object = emotion_object_add(evas);
+ emotion_object_init(object, NULL/*"gstreamer"*/);
+ emotion_object_file_set(object, "test.avi");
+
+ evas_object_move(object, 0, 0);
+ evas_object_resize(object, 100, 100);
+ evas_object_show(object);
+
+ return object;
+}
+
+#endif
--- /dev/null
+#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);
+ 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 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);
+
+#endif
--- /dev/null
+/emotion/utc_UIFW_emotion_object_add
+/emotion/utc_UIFW_emotion_object_init
+/emotion/utc_UIFW_emotion_object_file_set_get
+/emotion/utc_UIFW_emotion_object_play_set_get
+/emotion/utc_UIFW_emotion_object_position_set_get
+/emotion/utc_UIFW_emotion_object_play_length_get
+/emotion/utc_UIFW_emotion_object_ratio_get
+/emotion/utc_UIFW_emotion_object_audio_mute_set_get
+/emotion/utc_UIFW_emotion_object_module_option_set
+/emotion/utc_UIFW_emotion_object_border_set
+/emotion/utc_UIFW_emotion_object_bg_color_set
+/emotion/utc_UIFW_emotion_object_keep_aspect_set
+/emotion/utc_UIFW_emotion_object_seekable_get
+/emotion/utc_UIFW_emotion_object_play_speed_set_get
+/emotion/utc_UIFW_emotion_object_progress_status_get
+/emotion/utc_UIFW_emotion_object_size_get
+/emotion/utc_UIFW_emotion_object_smooth_scale_set
+/emotion/utc_UIFW_emotion_object_audio_volume_set_get
+/emotion/utc_UIFW_emotion_object_audio_channel_count
+/emotion/utc_UIFW_emotion_object_video_mute_set_get
+/emotion/utc_UIFW_emotion_object_video_channel_count
+/emotion/utc_UIFW_emotion_object_spu_channel_count
+/emotion/utc_UIFW_emotion_object_title_get
+/emotion/utc_UIFW_emotion_object_ref_file_get
+/emotion/utc_UIFW_emotion_object_ref_num_get
+/emotion/utc_UIFW_emotion_object_spu_button_count_get
+/emotion/utc_UIFW_emotion_object_spu_button_get
+/emotion/utc_UIFW_emotion_object_meta_info_get
+/emotion/utc_UIFW_emotion_object_vis_supported
+/emotion/utc_UIFW_emotion_object_last_position_save_load
+/emotion/utc_UIFW_emotion_object_image_get
+/emotion/utc_UIFW_emotion_init
+/emotion/utc_UIFW_emotion_shutdown
+/emotion/utc_UIFW_emotion_video_get
+/emotion/utc_UIFW_emotion_frame_new
+/emotion/utc_UIFW_emotion_video_pos_update
+/emotion/utc_UIFW_emotion_frame_resize
+/emotion/utc_UIFW_emotion_frame_refill
+/emotion/utc_UIFW_emotion_decode_stop
+/emotion/utc_UIFW_emotion_open_done
+/emotion/utc_UIFW_emotion_playback_started
+/emotion/utc_UIFW_emotion_playback_finished
+/emotion/utc_UIFW_emotion_audio_level_change
+/emotion/utc_UIFW_emotion_channels_change
+/emotion/utc_UIFW_emotion_title_set
+/emotion/utc_UIFW_emotion_progress_set
+/emotion/utc_UIFW_emotion_file_ref_set
+/emotion/utc_UIFW_emotion_spu_button_num_set
+/emotion/utc_UIFW_emotion_spu_button_set
+/emotion/utc_UIFW_emotion_seek_done
+/emotion/utc_UIFW_emotion_module_register
+/emotion/utc_UIFW_emotion_module_unregister
+/emotion/utc_UIFW_emotion_webcam_custom_get
+/emotion/utc_UIFW_emotion_object_progress_info_get
+/emotion/utc_UIFW_emotion_object_vis_set_get
+/emotion/utc_UIFW_emotion_object_event_simple_send
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_audio_level_change_p(void);
+static void utc_emotion_audio_level_change_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_audio_level_change_p, POSITIVE_TC_IDX},
+ { utc_emotion_audio_level_change_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_audio_level_change_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_audio_level_change(object);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_audio_level_change_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_audio_level_change(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_channels_change_p(void);
+static void utc_emotion_channels_change_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_channels_change_p, POSITIVE_TC_IDX},
+ { utc_emotion_channels_change_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_channels_change_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_channels_change(object);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_channels_change_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_channels_change(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_decode_stop_p(void);
+static void utc_emotion_decode_stop_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_decode_stop_p, POSITIVE_TC_IDX},
+ { utc_emotion_decode_stop_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_decode_stop_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_decode_stop(object);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_decode_stop_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_decode_stop(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_file_ref_set_p(void);
+static void utc_emotion_file_ref_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_file_ref_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_file_ref_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_file_ref_set_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_file_ref_set(object, "test.avi", 3);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_file_ref_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_file_ref_set(NULL, NULL, -5);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "emotion_private.h"
+#include "common.h"
+
+static void utc_emotion_frame_new_p(void);
+static void utc_emotion_frame_new_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_frame_new_p, POSITIVE_TC_IDX},
+ { utc_emotion_frame_new_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_frame_new_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_frame_new(object);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_frame_new_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_frame_new(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_frame_refill_p(void);
+static void utc_emotion_frame_refill_n(void);
+static void utc_emotion_frame_refill_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_frame_refill_p, POSITIVE_TC_IDX},
+ { utc_emotion_frame_refill_n, NEGATIVE_TC_IDX},
+ { utc_emotion_frame_refill_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_frame_refill_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_frame_refill(object, 5, 5);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_frame_refill_n(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ Evas_Object *object = init();
+ _emotion_frame_refill(object, -5, -5);
+ _emotion_frame_refill(object, 0, 0);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_frame_refill_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_frame_refill(NULL, 0, 0);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_frame_resize_p(void);
+static void utc_emotion_frame_resize_n(void);
+static void utc_emotion_frame_resize_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_frame_resize_p, POSITIVE_TC_IDX},
+ { utc_emotion_frame_resize_n, NEGATIVE_TC_IDX},
+ { utc_emotion_frame_resize_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_frame_resize_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_frame_resize(object, 100, 200, 0.5);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_frame_resize_n(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ Evas_Object *object = init();
+ _emotion_frame_resize(object, -100, -200, 0.0);
+ _emotion_frame_resize(object, 0, 0, 0.0);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_frame_resize_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_frame_resize(NULL, 0, 0, 0.0);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_init_p(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_init_p, POSITIVE_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_init_p(void)
+{
+ Eina_Bool res = emotion_init();
+
+ if (EINA_FALSE == res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_module_register_p(void);
+static void utc_emotion_module_register_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_module_register_p, POSITIVE_TC_IDX},
+ { utc_emotion_module_register_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static Eina_Bool
+module_open(Evas_Object *obj,
+ const Emotion_Video_Module **module,
+ void **video,
+ Emotion_Module_Options *opt)
+{
+ tet_printf("module_open");
+ return EINA_TRUE;
+}
+
+static void
+module_close(Emotion_Video_Module *module,
+ void *video)
+{
+ tet_printf("module_close");
+}
+
+static void utc_emotion_module_register_p(void)
+{
+ init();
+ _emotion_module_register("gstreamer", module_open, module_close);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_module_register_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_module_register(NULL, NULL, NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_module_unregister_p(void);
+static void utc_emotion_module_unregister_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_module_unregister_p, POSITIVE_TC_IDX},
+ { utc_emotion_module_unregister_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static Eina_Bool
+module_open(Evas_Object *obj,
+ const Emotion_Video_Module **module,
+ void **video,
+ Emotion_Module_Options *opt)
+{
+ tet_printf("module_open");
+ return EINA_TRUE;
+}
+
+static void
+module_close(Emotion_Video_Module *module,
+ void *video)
+{
+ tet_printf("module_close");
+}
+
+static void utc_emotion_module_unregister_p(void)
+{
+ init();
+ _emotion_module_register("gstreamer", module_open, module_close);
+ _emotion_module_unregister("gstreamer");
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_module_unregister_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_module_unregister(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_add_p(void);
+static void utc_emotion_object_add_n(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_add_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_add_n, NEGATIVE_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_add_p(void)
+{
+ Evas *evas = ecore_evas_get(ecore_evas);
+ Evas_Object *object = emotion_object_add(evas);
+
+ if (NULL == object) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_add_n(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ Evas_Object *object = emotion_object_add(NULL);
+
+ if (NULL != object) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_audio_channel_count_p(void);
+static void utc_emotion_object_audio_channel_count_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_audio_channel_count_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_audio_channel_count_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_audio_channel_count_p(void)
+{
+ Evas_Object *object = init();
+ int count = emotion_object_audio_channel_count(object);
+
+ if (1 != count) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_audio_channel_count_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_audio_channel_count(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_audio_mute_set_p(void);
+static void utc_emotion_object_audio_mute_set_n(void);
+static void utc_emotion_object_audio_mute_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_audio_mute_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_audio_mute_set_n, NEGATIVE_TC_IDX},
+ { utc_emotion_object_audio_mute_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_audio_mute_set_p(void)
+{
+ Evas_Object *object = init();
+ emotion_object_audio_mute_set(object, EINA_TRUE);
+ Eina_Bool res = emotion_object_audio_mute_get(object);
+
+ if (EINA_TRUE != res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_audio_mute_set_n(void)
+{
+ Evas_Object *object = init();
+ emotion_object_audio_mute_set(object, EINA_FALSE);
+ Eina_Bool res = emotion_object_audio_mute_get(object);
+
+ if (EINA_FALSE != res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_audio_mute_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_audio_mute_set(NULL, EINA_FALSE);
+ emotion_object_audio_mute_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_audio_volume_set_get_p(void);
+static void utc_emotion_object_audio_volume_set_get_n(void);
+static void utc_emotion_object_audio_volume_set_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_audio_volume_set_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_audio_volume_set_get_n, NEGATIVE_TC_IDX},
+ { utc_emotion_object_audio_volume_set_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_audio_volume_set_get_p(void)
+{
+ Evas_Object *object = init();
+ emotion_object_audio_volume_set(object, 0.5);
+ double volume = emotion_object_audio_volume_get(object);
+
+ if (0.5 != volume) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_audio_volume_set_get_n(void)
+{
+ Evas_Object *object = init();
+ emotion_object_audio_volume_set(object, 0.5);
+ emotion_object_audio_volume_set(object, -0.5);
+ emotion_object_audio_volume_set(object, 1.5);
+ double volume = emotion_object_audio_volume_get(object);
+
+ if (0.5 != volume) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_audio_volume_set_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_audio_volume_set(NULL, 5.0);
+ emotion_object_audio_volume_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_bg_color_set_p(void);
+static void utc_emotion_object_bg_color_set_n(void);
+static void utc_emotion_object_bg_color_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_bg_color_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_bg_color_set_n, NEGATIVE_TC_IDX},
+ { utc_emotion_object_bg_color_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_bg_color_set_p(void)
+{
+ int r = 0, g = 0, b = 0, a = 0;
+
+ Evas_Object *object = init();
+ ecore_main_loop_begin();
+ emotion_object_bg_color_set(object, 5, 4, 3, 2);
+ emotion_object_bg_color_get(object, &r, &g, &b, &a);
+
+ if (5 != r || 4 != g || 3 != b || 2 != a) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_printf("Expected value(rgba): (5,4,3,2), result value(rgba): (%d,%d,%d,%d)", r, g, b, a);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_bg_color_set_n(void)
+{
+ int r = 0, g = 0, b = 0, a = 0;
+
+ Evas_Object *object = init();
+ emotion_object_bg_color_set(object, -5, -4, -3, -2);
+ emotion_object_bg_color_get(object, &r, &g, &b, &a);
+
+ if (0 != r || 0 != g || 0 != b || 0 != a) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_bg_color_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_bg_color_set(NULL, -5, -4, -3, -2);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_border_set_p(void);
+static void utc_emotion_object_border_set_n(void);
+static void utc_emotion_object_border_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_border_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_border_set_n, NEGATIVE_TC_IDX},
+ { utc_emotion_object_border_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_border_set_p(void)
+{
+ int l = 0, r = 0, t = 0, b = 0;
+
+ Evas_Object *object = init();
+ emotion_object_border_set(object, 5, 4, 3, 2);
+ emotion_object_border_get(object, &l, &r, &t, &b);
+
+ if (5 != l || 4 != r || 3 != t || 2 != b) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_border_set_n(void)
+{
+ int l = 0, r = 0, t = 0, b = 0;
+
+ Evas_Object *object = init();
+ emotion_object_border_set(object, -5, -4, -3, -2);
+ emotion_object_border_get(object, &l, &r, &t, &b);
+
+ if (-5 != l || -4 != r || -3 != t || -2 != b) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_border_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_border_set(NULL, -5, -4, -3, -2);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_event_simple_send_p(void);
+static void utc_emotion_object_event_simple_send_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_event_simple_send_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_event_simple_send_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_event_simple_send_p(void)
+{
+ Evas_Object *object = init();
+
+ for (int event = EMOTION_EVENT_MENU1; event <= EMOTION_EVENT_10; ++event) {
+ emotion_object_event_simple_send(object, event);
+ }
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_event_simple_send_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_vis_set(NULL, EMOTION_EVENT_10 + 1);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_file_set_get_p(void);
+static void utc_emotion_object_file_set_get_n(void);
+static void utc_emotion_object_file_set_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_file_set_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_file_set_get_n, NEGATIVE_TC_IDX},
+ { utc_emotion_object_file_set_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_file_set_get_p(void)
+{
+ Evas_Object *object;
+ Eina_Bool res = EINA_FALSE;
+
+ signal(SIGSEGV, sigprocess);
+
+ Evas *evas = ecore_evas_get(ecore_evas);
+ object = emotion_object_add(evas);
+ emotion_object_init(object, NULL);
+ res = emotion_object_file_set(object, "test.avi");
+ const char *file_name = emotion_object_file_get(object);
+
+ if (EINA_FALSE == res || strcmp(file_name, "test.avi")) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_file_set_get_n(void)
+{
+ Evas *evas;
+ Evas_Object *object;
+ Eina_Bool res = EINA_FALSE;
+
+ signal(SIGSEGV, sigprocess);
+
+ evas = ecore_evas_get(ecore_evas);
+ object = emotion_object_add(evas);
+ emotion_object_init(object, NULL);
+ emotion_object_file_set(object, "test.avi");
+ res = emotion_object_file_set(object, "fail.png");
+ const char *file_name = emotion_object_file_get(object);
+ tet_printf("file name: %s", file_name);
+
+ if (EINA_FALSE != res || strcmp(file_name, "test.avi")) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_file_set_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_file_set(NULL, NULL);
+ emotion_object_file_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_image_get_p(void);
+static void utc_emotion_object_image_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_image_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_image_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_image_get_p(void)
+{
+ Evas_Object *object = init();
+ Evas_Object *image = emotion_object_image_get(object);
+
+ if (image == NULL) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_image_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_image_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_init_p(void);
+static void utc_emotion_object_init_n(void);
+static void utc_emotion_object_init_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_init_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_init_n, NEGATIVE_TC_IDX},
+ { utc_emotion_object_init_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_init_p(void)
+{
+ Evas *evas = NULL;
+ Evas_Object *object = NULL;
+ Eina_Bool res_gstreamer = EINA_FALSE;
+
+ signal(SIGSEGV, sigprocess);
+
+ evas = ecore_evas_get(ecore_evas);
+ object = emotion_object_add(evas);
+ res_gstreamer = emotion_object_init(object, NULL);
+
+ if (EINA_FALSE == res_gstreamer) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_init_n(void)
+{
+ Evas *evas = NULL;
+ Evas_Object *object = NULL;
+ Eina_Bool res = EINA_FALSE;
+
+ signal(SIGSEGV, sigprocess);
+
+ evas = ecore_evas_get(ecore_evas);
+ object = emotion_object_add(evas);
+ res = emotion_object_init(object, "test");
+
+ if (EINA_FALSE != res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_init_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_init(NULL, NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_keep_aspect_set_p(void);
+static void utc_emotion_object_keep_aspect_set_n(void);
+static void utc_emotion_object_keep_aspect_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_keep_aspect_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_keep_aspect_set_n, NEGATIVE_TC_IDX},
+ { utc_emotion_object_keep_aspect_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_keep_aspect_set_p(void)
+{
+ Evas_Object *object = init();
+ emotion_object_keep_aspect_set(object, EMOTION_ASPECT_KEEP_BOTH);
+ Emotion_Aspect res = emotion_object_keep_aspect_get(object);
+
+ if (EMOTION_ASPECT_KEEP_BOTH != res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_keep_aspect_set_n(void)
+{
+ Evas_Object *object = init();
+ emotion_object_keep_aspect_set(object, EMOTION_ASPECT_KEEP_BOTH);
+ emotion_object_border_set(object, 1, 1, 1, 1);
+ Emotion_Aspect res = emotion_object_keep_aspect_get(object);
+
+ if (EMOTION_ASPECT_CUSTOM != res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_keep_aspect_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_keep_aspect_set(NULL, EMOTION_ASPECT_KEEP_BOTH);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_last_position_save_load_p(void);
+static void utc_emotion_object_last_position_save_load_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_last_position_save_load_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_last_position_save_load_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_last_position_save_load_p(void)
+{
+ Evas_Object *object = init();
+ emotion_object_position_set(object, 5.0);
+ emotion_object_last_position_save(object);
+ emotion_object_position_set(object, 7.0);
+ emotion_object_last_position_load(object);
+ double last_position = emotion_object_position_get(object);
+ tet_printf("Last position: %d", last_position);
+
+ if (5.0 != last_position) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_last_position_save_load_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_last_position_save(NULL);
+ emotion_object_last_position_load(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_meta_info_get_p(void);
+static void utc_emotion_object_meta_info_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_meta_info_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_meta_info_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_meta_info_get_p(void)
+{
+ Evas_Object *object = init();
+ const char *title = emotion_object_meta_info_get(object, EMOTION_META_INFO_TRACK_TITLE);
+ const char *artist = emotion_object_meta_info_get(object, EMOTION_META_INFO_TRACK_ARTIST);
+ const char *album = emotion_object_meta_info_get(object, EMOTION_META_INFO_TRACK_ALBUM);
+ const char *year = emotion_object_meta_info_get(object, EMOTION_META_INFO_TRACK_YEAR);
+ const char *genre = emotion_object_meta_info_get(object, EMOTION_META_INFO_TRACK_GENRE);
+ const char *comment = emotion_object_meta_info_get(object, EMOTION_META_INFO_TRACK_COMMENT);
+ const char *disc_id = emotion_object_meta_info_get(object, EMOTION_META_INFO_TRACK_DISC_ID);
+ const char *count = emotion_object_meta_info_get(object, EMOTION_META_INFO_TRACK_COUNT);
+ tet_printf("title: %s, artist: %s, album: %s, year: %s, genre: %s, comment: %s, disc_id: %s, count: %s",
+ title, artist, album, year, genre, comment, disc_id, count);
+
+ // it was possible to set only these parameters with ffmpeg, so year, disc_id and count are not checked here
+ if (strcmp(artist, "Test artist") || strcmp(comment, "Test comment") || strcmp(genre, "Test genre") ||
+ strcmp(title, "Test title") || strcmp(album, "Test album")) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_meta_info_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_meta_info_get(NULL, EMOTION_META_INFO_TRACK_TITLE);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_module_option_set_p(void);
+static void utc_emotion_object_module_option_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_module_option_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_module_option_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_module_option_set_p(void)
+{
+ Evas_Object *object = init();
+ ecore_main_loop_begin();
+ emotion_object_video_mute_set(object, EINA_FALSE);
+ emotion_object_module_option_set(object, "video", "off");
+ Eina_Bool res_video = emotion_object_video_mute_get(object);
+
+ emotion_object_audio_mute_set(object, EINA_FALSE);
+ emotion_object_module_option_set(object, "audio", "off");
+ Eina_Bool res_audio = emotion_object_audio_mute_get(object);
+
+ if (EINA_TRUE != res_video || EINA_TRUE != res_audio) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_module_option_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_module_option_set(NULL, "video", "off");
+ emotion_object_module_option_set(NULL, "audio", "off");
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_play_length_get_p(void);
+static void utc_emotion_object_play_length_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_play_length_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_play_length_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_play_length_get_p(void)
+{
+ Evas_Object *object = init();
+ ecore_main_loop_begin();
+ double length = emotion_object_play_length_get(object);
+
+ if (10 != length) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_printf("Expected value: 10, return value: %d", length);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_play_length_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_play_length_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_play_set_p(void);
+static void utc_emotion_object_play_set_n(void);
+static void utc_emotion_object_play_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_play_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_play_set_n, NEGATIVE_TC_IDX},
+ { utc_emotion_object_play_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_play_set_p(void)
+{
+ Evas_Object *object = init();
+
+ emotion_object_play_set(object, EINA_TRUE);
+
+ ecore_main_loop_begin();
+
+ Eina_Bool res = emotion_object_play_get(object);
+
+ if (EINA_FALSE == res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_play_set_n(void)
+{
+ Evas_Object *object = init();
+ emotion_object_play_set(object, EINA_FALSE);
+ Eina_Bool res = emotion_object_play_get(object);
+
+ if (EINA_FALSE != res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_play_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_play_set(NULL, EINA_TRUE);
+ emotion_object_play_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_play_speed_set_p(void);
+static void utc_emotion_object_play_speed_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_play_speed_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_play_speed_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_play_speed_set_p(void)
+{
+ Evas_Object *object = init();
+ ecore_main_loop_begin();
+ emotion_object_play_speed_set(object, 5.0);
+ double play_speed = emotion_object_play_speed_get(object);
+
+ if (5.0 != play_speed) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_printf("Expected value: 5.0, return value: %f", play_speed);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_play_speed_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_play_speed_set(NULL, 5.0);
+ emotion_object_play_speed_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_position_set_get_p(void);
+static void utc_emotion_object_position_set_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_position_set_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_position_set_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_position_set_get_p(void)
+{
+ Evas_Object *object = init();
+ ecore_main_loop_begin();
+ emotion_object_position_set(object, 5);
+ double position = emotion_object_position_get(object);
+
+ if (5 != position) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_printf("Expected value: 5, return value: %d", position);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_position_set_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_position_set(NULL, 5);
+ emotion_object_position_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_progress_info_get_p(void);
+static void utc_emotion_object_progress_info_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_progress_info_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_progress_info_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_progress_info_get_p(void)
+{
+ Evas_Object *object = init();
+ const char *progress_info = emotion_object_progress_info_get(object);
+ tet_printf("progress_info: %s", progress_info);
+
+ if (NULL == progress_info) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_progress_info_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_progress_info_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_progress_status_get_p(void);
+static void utc_emotion_object_progress_status_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_progress_status_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_progress_status_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_progress_status_get_p(void)
+{
+ double position = 3.0;
+
+ Evas_Object *object = init();
+ ecore_main_loop_begin();
+ emotion_object_position_set(object, position);
+ double status = emotion_object_progress_status_get(object);
+
+ if (position / emotion_object_play_length_get(object) != status) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_printf("Expected value: %f, return value: %f", position / emotion_object_play_length_get(object), status);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_progress_status_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_progress_status_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_ratio_get_p(void);
+static void utc_emotion_object_ratio_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_ratio_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_ratio_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_ratio_get_p(void)
+{
+ Evas_Object *object = init();
+ ecore_main_loop_begin();
+ double ratio = emotion_object_ratio_get(object);
+
+ if ((double)436 / 344 != ratio) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_printf("Expeced value: %f, result value: %f", (double)436 / 344, ratio);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_ratio_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_ratio_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_ref_file_get_p(void);
+static void utc_emotion_object_ref_file_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_ref_file_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_ref_file_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_ref_file_get_p(void)
+{
+ Evas_Object *object = init();
+ const char *file = emotion_object_ref_file_get(object);
+ tet_printf("file: %s", file);
+
+ if (file != NULL) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_ref_file_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_ref_file_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_ref_num_get_p(void);
+static void utc_emotion_object_ref_num_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_ref_num_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_ref_num_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_ref_num_get_p(void)
+{
+ Evas_Object *object = init();
+ int num = emotion_object_ref_num_get(object);
+
+ if (num != 0) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_ref_num_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_ref_num_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_seekable_get_p(void);
+static void utc_emotion_object_seekable_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_seekable_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_seekable_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_seekable_get_p(void)
+{
+ Evas_Object *object = init();
+ ecore_main_loop_begin();
+ Eina_Bool res = emotion_object_seekable_get(object);
+
+ if (EINA_TRUE != res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_seekable_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_seekable_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_size_get_p(void);
+static void utc_emotion_object_size_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_size_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_size_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_size_get_p(void)
+{
+ int w = 0, h = 0;
+
+ Evas_Object *object = init();
+ ecore_main_loop_begin();
+ emotion_object_size_get(object, &w, &h);
+
+ if (436 != w || 344 != h) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_size_get_null(void)
+{
+ int w = 0, h = 0;
+
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_size_get(NULL, &w, &h);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_smooth_scale_set_p(void);
+static void utc_emotion_object_smooth_scale_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_smooth_scale_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_smooth_scale_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_smooth_scale_set_p(void)
+{
+ Evas_Object *object = init();
+ emotion_object_smooth_scale_set(object, EINA_TRUE);
+ Eina_Bool smooth = emotion_object_smooth_scale_get(object);
+
+ if (EINA_TRUE != smooth) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_smooth_scale_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_smooth_scale_set(NULL, EINA_TRUE);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_spu_button_count_get_p(void);
+static void utc_emotion_object_spu_button_count_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_spu_button_count_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_spu_button_count_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_spu_button_count_get_p(void)
+{
+ Evas_Object *object = init();
+ int button_count = emotion_object_spu_button_count_get(object);
+
+ if (button_count != 0) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_spu_button_count_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_spu_button_count_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_spu_button_get_p(void);
+static void utc_emotion_object_spu_button_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_spu_button_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_spu_button_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_spu_button_get_p(void)
+{
+ Evas_Object *object = init();
+ int button = emotion_object_spu_button_get(object);
+ tet_printf("button: %d", button);
+
+ if (button != 0) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_spu_button_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_spu_button_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_spu_channel_count_p(void);
+static void utc_emotion_object_spu_channel_count_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_spu_channel_count_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_spu_channel_count_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_spu_channel_count_p(void)
+{
+ Evas_Object *object = init();
+ int count = emotion_object_spu_channel_count(object);
+
+ if (0 != count) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_spu_channel_count_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_spu_channel_count(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_title_get_p(void);
+static void utc_emotion_object_title_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_title_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_title_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_title_get_p(void)
+{
+ Evas_Object *object = init();
+ const char *title = emotion_object_title_get(object);
+
+ if (title != NULL) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_title_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_title_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_video_channel_count_p(void);
+static void utc_emotion_object_video_channel_count_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_video_channel_count_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_video_channel_count_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_video_channel_count_p(void)
+{
+ Evas_Object *object = init();
+ int count = emotion_object_video_channel_count(object);
+
+ if (1 != count) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_video_channel_count_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_video_channel_count(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_video_mute_set_p(void);
+static void utc_emotion_object_video_mute_set_n(void);
+static void utc_emotion_object_video_mute_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_video_mute_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_video_mute_set_n, NEGATIVE_TC_IDX},
+ { utc_emotion_object_video_mute_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_video_mute_set_p(void)
+{
+ Evas_Object *object = init();
+ emotion_object_video_mute_set(object, EINA_TRUE);
+ Eina_Bool res = emotion_object_video_mute_get(object);
+
+ if (EINA_TRUE != res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_video_mute_set_n(void)
+{
+ Evas_Object *object = init();
+ emotion_object_video_mute_set(object, EINA_FALSE);
+ Eina_Bool res = emotion_object_video_mute_get(object);
+
+ if (EINA_FALSE != res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_video_mute_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_video_mute_set(NULL, EINA_FALSE);
+ emotion_object_video_mute_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_vis_set_get_p(void);
+static void utc_emotion_object_vis_set_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_vis_set_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_vis_set_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_vis_set_get_p(void)
+{
+ Evas_Object *object = init();
+
+ for (int i = EMOTION_VIS_GOOM; i <= EMOTION_VIS_LIBVISUAL_PLASMA; ++i) {
+ emotion_object_vis_set(object, i);
+ Emotion_Vis vis = emotion_object_vis_get(object);
+
+ if (vis != i) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ }
+
+// emotion_object_vis_set(object, EMOTION_VIS_GOOM);
+// Emotion_Vis vis = emotion_object_vis_get(object);
+// if (vis != EMOTION_VIS_GOOM) {
+//
+// }
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_BUMPSCOPE);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_CORONA);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_DANCING_PARTICLES);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_GDKPIXBUF);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_G_FORCE);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_GOOM);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_INFINITE);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_JAKDAW);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_JESS );
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_LV_ANALYSER);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_LV_FLOWER);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_LV_GLTEST);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_LV_SCOPE);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_MADSPIN);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_NEBULUS);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_OINKSIE);
+// vis = emotion_object_vis_get(object);
+//
+// emotion_object_vis_set(object, EMOTION_VIS_LIBVISUAL_PLASMA);
+// vis = emotion_object_vis_get(object);
+//
+// if (goom != EINA_FALSE || bumpscope != EINA_FALSE || corona != EINA_FALSE || dancing_particles != EINA_FALSE
+// || gdbpixbuf != EINA_FALSE || g_force != EINA_FALSE || goom2 != EINA_FALSE || infinite != EINA_FALSE
+// || jakdaw != EINA_FALSE || jess != EINA_FALSE || analyser != EINA_FALSE || flower != EINA_FALSE
+// || madspin != EINA_FALSE || nebulus != EINA_FALSE || oinksie != EINA_FALSE || plasma != EINA_FALSE) {
+// tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+// tet_result(TET_FAIL);
+// return;
+// }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_vis_set_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_vis_set(NULL, EMOTION_META_INFO_TRACK_TITLE);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_object_vis_supported_p(void);
+static void utc_emotion_object_vis_supported_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_object_vis_supported_p, POSITIVE_TC_IDX},
+ { utc_emotion_object_vis_supported_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_object_vis_supported_p(void)
+{
+ Evas_Object *object = init();
+
+ Eina_Bool goom = emotion_object_vis_supported(object, EMOTION_VIS_GOOM);
+ Eina_Bool bumpscope = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_BUMPSCOPE);
+ Eina_Bool corona = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_CORONA);
+ Eina_Bool dancing_particles = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_DANCING_PARTICLES);
+ Eina_Bool gdbpixbuf = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_GDKPIXBUF);
+ Eina_Bool g_force = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_G_FORCE);
+ Eina_Bool goom2 = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_GOOM);
+ Eina_Bool infinite = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_INFINITE);
+ Eina_Bool jakdaw = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_JAKDAW);
+ Eina_Bool jess = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_JESS );
+ Eina_Bool analyser = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_LV_ANALYSER);
+ Eina_Bool flower = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_LV_FLOWER);
+ Eina_Bool gltest = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_LV_GLTEST);
+ Eina_Bool scope = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_LV_SCOPE);
+ Eina_Bool madspin = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_MADSPIN);
+ Eina_Bool nebulus = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_NEBULUS);
+ Eina_Bool oinksie = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_OINKSIE);
+ Eina_Bool plasma = emotion_object_vis_supported(object, EMOTION_VIS_LIBVISUAL_PLASMA);
+
+ tet_printf("goom: %d, bumpscope: %d, corona: %d, dancing_particles: %d, gdbpixbuf: %d, \
+ g_force: %d, goom2: %d, infinite: %d, jakdaw: %d, jess: %d, analyser: %d, flower: %d, \
+ gltest: %d, scope: %d, madspin: %d, nebulus: %d, oinksie: %d, plasma: %d",
+ goom, bumpscope, corona, dancing_particles, gdbpixbuf, g_force, goom2, infinite,
+ jakdaw, jess, analyser, flower, gltest, scope, madspin, nebulus, oinksie, plasma);
+
+ if (goom != EINA_FALSE || bumpscope != EINA_FALSE || corona != EINA_FALSE || dancing_particles != EINA_FALSE
+ || gdbpixbuf != EINA_FALSE || g_force != EINA_FALSE || goom2 != EINA_FALSE || infinite != EINA_FALSE
+ || jakdaw != EINA_FALSE || jess != EINA_FALSE || analyser != EINA_FALSE || flower != EINA_FALSE
+ || madspin != EINA_FALSE || nebulus != EINA_FALSE || oinksie != EINA_FALSE || plasma != EINA_FALSE) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_object_vis_supported_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ emotion_object_vis_supported(NULL, EMOTION_META_INFO_TRACK_TITLE);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_open_done_p(void);
+static void utc_emotion_open_done_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_open_done_p, POSITIVE_TC_IDX},
+ { utc_emotion_open_done_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_open_done_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_open_done(object);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_open_done_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_open_done(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_playback_finished_p(void);
+static void utc_emotion_playback_finished_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_playback_finished_p, POSITIVE_TC_IDX},
+ { utc_emotion_playback_finished_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_playback_finished_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_playback_finished(object);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_playback_finished_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_playback_finished(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_playback_started_p(void);
+static void utc_emotion_playback_started_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_playback_started_p, POSITIVE_TC_IDX},
+ { utc_emotion_playback_started_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_playback_started_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_playback_started(object);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_playback_started_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_playback_started(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_progress_set_p(void);
+static void utc_emotion_progress_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_progress_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_progress_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_progress_set_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_progress_set(object, "info", 0.5);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_progress_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_progress_set(NULL, NULL, 0.0);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_seek_done_p(void);
+static void utc_emotion_seek_done_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_seek_done_p, POSITIVE_TC_IDX},
+ { utc_emotion_seek_done_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_seek_done_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_seek_done(object);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_seek_done_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_seek_done(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+
+static void utc_emotion_shutdown_p(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_shutdown_p, POSITIVE_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_shutdown_p(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ Eina_Bool res = emotion_shutdown();
+
+ if (EINA_FALSE == res) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_spu_button_num_set_p(void);
+static void utc_emotion_spu_button_num_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_spu_button_num_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_spu_button_num_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_spu_button_num_set_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_spu_button_num_set(object, 2);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_spu_button_num_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_spu_button_num_set(NULL, -2);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_spu_button_set_p(void);
+static void utc_emotion_spu_button_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_spu_button_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_spu_button_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_spu_button_set_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_spu_button_set(object, 2);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_spu_button_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_spu_button_set(NULL, -2);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_title_set_p(void);
+static void utc_emotion_title_set_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_title_set_p, POSITIVE_TC_IDX},
+ { utc_emotion_title_set_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_title_set_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_title_set(object, "title");
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_title_set_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_title_set(NULL, NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_video_get_p(void);
+static void utc_emotion_video_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_video_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_video_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_video_get_p(void)
+{
+ Evas_Object *object = init();
+ void *video = _emotion_video_get(object);
+
+ if (video == NULL) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_video_get_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_video_get(NULL);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_video_pos_update_p(void);
+static void utc_emotion_video_pos_update_n(void);
+static void utc_emotion_video_pos_update_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_video_pos_update_p, POSITIVE_TC_IDX},
+ { utc_emotion_video_pos_update_n, NEGATIVE_TC_IDX},
+ { utc_emotion_video_pos_update_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_video_pos_update_p(void)
+{
+ Evas_Object *object = init();
+ _emotion_video_pos_update(object, 5.0, 5.0);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_video_pos_update_n(void)
+{
+ Evas_Object *object = init();
+ _emotion_video_pos_update(object, -5.0, -5.0);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_video_pos_update_null(void)
+{
+ signal(SIGSEGV, sigprocess);
+
+ _emotion_video_pos_update(NULL, 0.0, 0.0);
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#include <tet_api.h>
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <signal.h>
+#include "common.h"
+#include "emotion_private.h"
+
+static void utc_emotion_webcam_custom_get_p(void);
+static void utc_emotion_webcam_custom_get_null(void);
+
+struct tet_testlist tet_testlist[] = {
+ { utc_emotion_webcam_custom_get_p, POSITIVE_TC_IDX},
+ { utc_emotion_webcam_custom_get_null, NULL_TC_IDX},
+ { NULL, 0 },
+};
+
+static void utc_emotion_webcam_custom_get_p(void)
+{
+ init();
+ const char *launch = emotion_webcam_custom_get("/dev/webcam");
+
+ if (launch == NULL) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
+static void utc_emotion_webcam_custom_get_null(void)
+{
+ init();
+ const char *launch = emotion_webcam_custom_get(NULL);
+
+ if (launch != NULL) {
+ tet_printf("[TET_FAIL]:: %s[%d] : Test has failed..", __FILE__, __LINE__);
+ tet_result(TET_FAIL);
+ return;
+ }
+
+ tet_printf("[TET_PASS]:: %s[%d] : Test has passed..", __FILE__, __LINE__);
+ tet_result(TET_PASS);
+}
+
--- /dev/null
+#!/bin/sh
+
+. ./_export_env.sh # setting environment variables
+
+export TET_SUITE_ROOT=`pwd`
+FILE_NAME_EXTENSION=`date +%s`
+
+RESULT_DIR=results
+HTML_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.html
+JOURNAL_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.journal
+
+mkdir -p $RESULT_DIR
+
+tcc -e -j $JOURNAL_RESULT -p ./
+#grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT
+grw -c 7 -f chtml -o $HTML_RESULT $JOURNAL_RESULT
+
--- /dev/null
+all
+ ^EMOTION
+##### Scenarios for TEST #####
+
+# Test scenario
+
+EMOTION
+ :include:/emotion/tslist
--- /dev/null
+TET_OUTPUT_CAPTURE=True # capture option for build operation checking
+TET_BUILD_TOOL=make # build with using make command
+TET_BUILD_FILE=-f Makefile # execution file (Makefile) for build
+TET_API_COMPLIANT=True # use TET API in Test Case ?
+TET_PASS_TC_NAME=True # report passed TC name in Journal file?
--- /dev/null
+TET_OUTPUT_CAPTURE=True # capture option
+TET_CLEAN_TOOL= make clean # clean tool
+TET_CLEAN_FILE= Makefile # file for clean
+TET_API_COMPLIANT=True # TET API useage
+TET_PASS_TC_NAME=True # showing name , passed TC
--- /dev/null
+TET_OUTPUT_CAPTURE=True # capturing execution or not
+TET_EXEC_TOOL= # ex) exec : execution tool set up/ Optional
+TET_EXEC_FILE= # ex) exectool : execution file/ Optional
+TET_API_COMPLIANT=True # Test case or Tool usesTET API?
+TET_PASS_TC_NAME=True # showing Passed TC name ?
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 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 "$@"
+ ./configure -C "$@"
fi
--- /dev/null
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+m4_define([v_maj], [1])
+m4_define([v_min], [7])
+m4_define([v_mic], [99])
+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
+dnl 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 <stdio.h>
+#include <linux/videodev2.h>
+ ]],
+ [[
+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
MAINTAINERCLEANFILES = Makefile.in
-EDJE_CC = edje_cc
+EDJE_CC = @edje_cc@
EDJE_FLAGS = -v -id $(top_srcdir)/data -fd $(top_srcdir)/data
-filesdir = $(datadir)/emotion/data
-files_DATA = theme.edj
+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 \
video_frame_top.png \
whb.png \
window_inner_shadow.png \
-Vera.ttf \
-theme.edc
+theme.edc \
+icon.edc
-theme.edj: Makefile
+theme.edj: Makefile theme.edc
$(EDJE_CC) $(EDJE_FLAGS) \
$(top_srcdir)/data/theme.edc \
$(top_builddir)/data/theme.edj
+icon.edj: Makefile icon.edc
+ $(EDJE_CC) $(EDJE_FLAGS) \
+ $(top_srcdir)/data/icon.edc \
+ $(top_builddir)/data/icon.edj
+
clean-local:
rm -f *.edj
--- /dev/null
+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";
+ }
+ }
+ }
+ }
+}
image: "pnl.png" COMP;
}
-fonts {
- font: "Vera.ttf" "Vera";
-}
-
collections {
group {
name: "background";
color2: 0 0 0 255;
text {
text: "Video Progress";
- font: "Vera";
+ font: "Sans";
size: 6;
align: 0.0 1.0;
};
color: 0 0 0 255;
text {
text: "Video Speed";
- font: "Vera";
+ 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;
};
color2: 0 0 0 255;
text {
text: "XX:XX:XX / XX:XX:XX";
- font: "Vera";
+ font: "Sans";
size: 10;
align: 1.0 1.0;
min: 1 1;
--- /dev/null
+emotion (1.0.0+svn.70375slp2+build02) unstable; urgency=low
+
+ * Package Upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_1.0.0+svn.70375slp2+build02
+
+ -- Myungjae Lee <mjae.lee@samsung.com> Wed, 25 Apr 2012 17:30:10 +0900
+
+emotion (1.0.0+svn.70375slp2+build01) unstable; urgency=low
+
+ * Pakcage Upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_1.0.0+svn.70375slp2+build01
+
+ -- Myungjae Lee <mjae.lee@samsung.com> Wed, 25 Apr 2012 15:15:36 +0900
+
+emotion (1.0.0+svn.70278slp2+build01) unstable; urgency=low
+
+ * Package Upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_1.0.0+svn.70278slp2+build01
+
+ -- Jaehwan Kim <jae.hwan.kim@samsung.com> Mon, 23 Apr 2012 15:30:14 +0900
+
+emotion (1.0.0+svn.69824slp2+build01) unstable; urgency=low
+
+ * Package Upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_1.0.0+svn.69824slp2+build01
+
+ -- Jeonghyun Yun <jh0506.yun@samsung.com> Fri, 06 Apr 2012 18:25:12 +0900
+
+emotion (0.1.0+svn.69618slp2+build01) unstable; urgency=low
+
+ * Package Upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_0.1.0+svn.69618slp2+build01
+
+ -- Jeonghyun Yun <jh0506.yun@samsung.com> Wed, 28 Mar 2012 14:31:28 +0900
+
+emotion (0.1.0+svn.69438slp2+build02) unstable; urgency=low
+
+ * Package Upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_0.1.0+svn.69438slp2+build02
+
+ -- Jeonghyun Yun <jh0506.yun@samsung.com> Sun, 18 Mar 2012 14:23:12 +0900
+
+emotion (0.1.0+svn.69438slp2+build01) unstable; urgency=low
+
+ * EFL migration
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_0.1.0+svn.69438slp2+build01
+
+ -- Jeonghyun Yun <jh0506.yun@samsung.com> Fri, 16 Mar 2012 21:51:33 +0900
+
+emotion (0.1.0+svn.68849slp2+build01) unstable; urgency=low
+
+ * Package Upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_0.1.0+svn.68849slp2+build01
+
+ -- Jeonghyun Yun <jh0506.yun@samsung.com> Wed, 07 Mar 2012 16:45:45 +0900
+
+emotion (0.1.0+svn.68464slp2+build01) unstable; urgency=low
+
+ * Package upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_0.1.0+svn.68464slp2+build01
+
+ -- Jeonghyun Yun <jh0506.yun@samsung.com> Fri, 02 Mar 2012 06:35:57 -0500
+
+emotion (0.1.0+svn.67705slp2+build01) unstable; urgency=low
+
+ * Package Upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_0.1.0+svn.67705slp2+build01
+
+ -- Jaehwan Kim <jae.hwan.kim@samsung.com> Wed, 15 Feb 2012 19:03:23 +0900
+
+emotion (0.1.0+svn.66791slp2+build01) unstable; urgency=low
+
+ * Package Upload
+ * Git: slp/pkgs/e/emotion
+ * Tag: emotion_0.1.0+svn.66791slp2+build01
+
+ -- Jaehwan Kim <jae.hwan.kim@samsung.com> Mon, 16 Jan 2012 18:38:15 +0900
+
+emotion (0.1.0+svn.65137slp2+build02) unstable; urgency=low
+
+ * Rebuild after adding package to default.xml
+
+ -- Mike McCormack <mj.mccormack@samsung.com> Mon, 14 Nov 2011 19:18:20 +0900
+
+emotion (0.1.0+svn.65137slp2+build01) unstable; urgency=low
+
+ * Initial release, based on @65137
+
+ -- Mike McCormack <mj.mccormack@samsung.com> Mon, 14 Nov 2011 18:54:14 +0900
Source: emotion
Priority: optional
Section: libs
-Maintainer: Falko Schmidt <falko@alphagemini.org>
-Build-Depends: cdbs, debhelper (>= 6), pkg-config, libeet-dev, libevas-dev, libedje-dev, libecore-dev, libembryo-dev, libxine-dev (>=1.1.0), libgstreamer0.10-dev, libgstreamer-plugins-base0.10-dev
-Standards-Version: 3.7.3
+Maintainer: Jaehwan Kim <jae.hwan.kim@samsung.com>, Myoungwoon Kim <myoungwoon.kim@samsung.com>, Jeonghyun Yun <jh0506.yun@samsung.com>
+Original-Maintainer: Falko Schmidt <falko@alphagemini.org>
+Build-Depends: cdbs, debhelper (>= 6), libeet-dev, libevas-dev, libedje-dev, libecore-dev, libembryo-dev, libgstreamer0.10-dev, libgstreamer-plugins-base0.10-dev
+Standards-Version: 3.8.2
Homepage: http://www.enlightenment.org
Package: libemotion0
Section: libs
Architecture: any
-Depends: ${shlibs:Depends}
-Provides: libemotion
+Depends: ${shlibs:Depends}, libemotion0-gstreamer
+Provides: libemotion, libemotion-bin
+Replaces: libemotion-bin
Description: Video playback library used in Enlightenment DR0.17
This is the emotion library, a wrapper library used in the next-generation
Enlightenment suite for video playback.
.
This package contains the shared libraries.
-Package: libemotion-dev
+Package: libemotion0-dev
Section: libdevel
Architecture: any
Depends: libemotion0 (= ${Source-Version}), libevas-dev, libecore-dev
-Provides: libemotion0-dev
+Provides: libemotion-dev
+Replaces: libemotion-dev
Description: Headers, static libraries and documentation for Emotion
This package contains development files for the Emotion library, a wrapper
library used in the next-generation Enlightenment suite for video playback.
This package contains headers and static libraries for development with
libemotion.
-Package: libemotion-xine
-Section: libs
-Architecture: any
-Depends: ${shlibs:Depends}, libemotion0, libxine1 (>=1.1.0)
-Provides: libemotion-xine
-Description: Video playback library used in Enlightenment DR0.17
- This is the emotion library, a wrapper library used in the next-generation
- Enlightenment suite for video playback.
- .
- This package provides the xine module for emotion.
-
-Package: libemotion-gstreamer
+Package: libemotion0-gstreamer
Section: libs
Architecture: any
Depends: ${shlibs:Depends}, libemotion0, gstreamer0.10-plugins-good
Provides: libemotion-gstreamer
+Replaces: libemotion-gstreamer
Description: Video playback library used in Enlightenment DR0.17
This is the emotion library, a wrapper library used in the next-generation
Enlightenment suite for video playback.
.
This package provides the gstreamer module for emotion.
-
-Package: libemotion-bin
-Section: x11
-Architecture: any
-Depends: ${shlibs:Depends}
-Provides: libemotion0-bin
-Description: Test programs for Emotion
- This is the emotion library, a wrapper library used in the next-generation
- Enlightenment suite for video playback.
- .
- This package contains test programs for the Emotion library.
--- /dev/null
+debian/tmp/usr/include/*
+debian/tmp/usr/lib/pkgconfig/*
+debian/tmp/usr/lib/*.a
+debian/tmp/usr/lib/*.so
--- /dev/null
+debian/tmp/usr/lib/emotion/*gstreamer*.so
debian/tmp/usr/lib/libemotion.so.*
+debian/tmp/usr/bin/emotion_*
+debian/tmp/usr/share/emotion/data/theme.edj
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/autotools.mk
-DEB_MAKE_CLEAN_TARGET := clean
+DEB_CONFIGURE_SCRIPT := ./autogen.sh
+DEB_MAKE_CLEAN_TARGET := distclean
+DEB_CONFIGURE_EXTRA_FLAGS := --disable-rpath --enable-xine=no --disable-doc
clean::
- ./autogen.sh --prefix=/usr $(DEB_CONFIGURE_EXTRA_FLAGS)
+ [ ! -f Makefile ] || make distclean
--- /dev/null
+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
--- /dev/null
+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
+/*
+ Author:
+ Andres Blanc <andresblanc@gmail.com>
+ DaveMDS Andreoli <dave@gurumeditation.it>
+
+ 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 {
- background: url("b.png");
- background-repeat: repeat-x;
- background-position: top left;
- background-color: #f4f4f4;
- text-align: center;
- font-family: sans-serif;
- padding: 0;
- margin: 0;
-}
-
-div.main {
- margin: 1em auto;
- vertical-align: top;
- font-family: "Bitstream Vera", "Vera", "Trebuchet MS", Trebuchet, Tahoma, sans-serif;
- color: #444444;
- font-size: 0.8em;
- text-align: justify;
- width: 80%;
-}
-
-td.t { background-image:url("t.gif"); }
-td.t[class] { background-image:url("t.png"); }
-td.tl { background-image:url("tl.gif"); }
-td.tl[class] { background-image:url("tl.png"); }
-
-td.nav, td.lnav, td.rnav {
- align: middle;
- text-align: center;
- vertical-align: middle;
- width: 100px;
- height: 25px;
- font-family: "Bitstream Vera", "Vera", "Trebuchet MS", Trebuchet, Tahoma, sans-serif;
- color: #000000;
- font-size: 9px;
- font-weight: bold;
- white-space: no-wrap;
-}
-
-td.lnav[class] { background-image:url("n.png"); }
-td.lnav[class] { background-image:url("n.png"); }
-td.rnav { background-image:url("n.gif"); }
-td.rnav[class] { background-image:url("n.png"); }
-
-hr {
- width: 200px;
- height: 1px;
- background: #dddddd;
- border: 0;
-}
-
-p { color: #444444 ;}
-p.tiny, small {
- color: #888888;
- font-size: 0.5em;
-}
-
-h1 {
- text-align: center;
- font-size: 1.3em;
-}
-
-h2 { font-size: 1.1em; }
-h3 { font-size: 0.9em; }
-
-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; }
-
-a:link {
- color: #445566;
- text-decoration: underline;
-}
-
-a:visited {
- color: #667788;
- text-decoration: underline;
-}
-
-a:active {
- color: #88cccc;
- text-decoration: none;
-}
-
-a:hover {
- color: #112266;
- text-decoration: underline;
-}
-
-a.nav {
- text-decoration: none;
- display: block;
-}
-
-a.nav:link, a.nav:visited { color: #888888; }
-a.nav:active { color: #000000; }
-a.nav:hover { color: #444444; }
-a.code:link, a.code:visited { text-decoration: none; }
-
-div.fragment {
- font-size: 1em;
- border: 1px dotted #cccccc;
- background-color: #ffffff;
- text-align: left;
- vertical-align: middle;
- padding: 2px;
- margin-left: 25px;
- margin-right: 25px;
- overflow: auto;
-}
-
-td.indexkey {
- font-weight: bold;
- padding-left: 10px;
- padding-right: 0;
- padding-top: 2px;
- padding-bottom: 0px;
- margin: 0;
- margin-top: 2px;
- margin-bottom: 2px;
- border: 1px dotted #cccccc;
- border-right: 0px dotted #cccccc;
-}
-
-td.indexvalue {
- font-style: italic;
- padding-right: 10px;
- padding-left: 0;
- padding-top: 2px;
- padding-bottom: 2px;
- margin: 0;
- margin-top: 2px;
- margin-bottom: 2px;
- border: 1px dotted #cccccc;
- border-left: 0px dotted #cccccc;
-}
-
-.mdescRight { font-style: italic; }
-.memitem {
- padding-left: 2px;
- padding-right: 2px;
- border: 1px dotted #cccccc;
- background-color: #ffffff;
-}
-.memname {
- white-space: nowrap;
- font-weight: bold;
-}
-.paramname { font-weight: normal; }
-
-div.ah {
- border: thin solid #888888;
- font-weight: bold;
- margin-bottom: 3px;
- margin-top: 3px;
+ /*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%;
}
--- /dev/null
+/**
+ * @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.
+ */
+
+ <div id="push"></div>
+ </div> <!-- #content -->
+ </div> <!-- .layout -->
+
+ </div> <!-- #container -->
+
+
+ <div id="footer">
+ <table><tr>
+ <td class="copyright">Copyright ©$year Enlightenment</td>
+ <td class="generated">Docs generated $datetime</td>
+ </tr></table>
</div>
- <hr />
- <p class="tiny">Copyright © Enlightenment.org</p>
- <p class="tiny">$projectname Documentation Generated: $datetime</p>
- </body>
+
+
+</body>
</html>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
<html>
- <head>
- <title>$title</title>
- <link href="e.css" rel="stylesheet" type="text/css" />
- </head>
+<head>
+ <title>$title</title>
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8">
+ <meta name="author" content="Andres Blanc" >
+
+ <link rel="icon" href="img/favicon.png" type="image/x-icon">
+ <link rel="shortcut icon" href="img/favicon.png" type="image/x-icon">
+ <link rel="icon" href="img/favicon.png" type="image/ico">
+ <link rel="shortcut icon" href="img/favicon.png" type="image/ico">
+
+ <link rel="stylesheet" type="text/css" href="e.css">
+ <link rel="stylesheet" type="text/css" href="edoxy.css">
+</head>
<body>
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tr>
- <td class="t" width="50%" valign="top" align="left">
- <table width="100px" height="100px" border="0" cellpadding="0" cellspacing="0">
- <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=index">Home</a></td></tr>
- <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=news">News</a></td></tr>
- <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=about">About</a></td></tr>
- <tr><td class="rnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=download">Download</a></td></tr>
- </table>
- </td>
- <td class="tl" width="612" height="250" valign="bottom" align="center">
- <img src="_.gif" width="612" height="1" />
- <table border="0" cellpadding="0" cellspacing="4px">
- <tr>
- <td class='nav'><a class='nav' href="index.html">Main Page</a></td>
- <td class="nav"><a class="nav" href="emotion_8c.html">API Reference</a></td>
- <td class="nav"><a class="nav" href="pages.html">Related Pages</a></td>
- </tr>
- </table>
- <hr />
- </td>
- <td class="t" width="50%" valign="top" align="right">
- <table width="100px" height="100px" border="0" cellpadding="0" cellspacing="0">
- <tr><td class="rnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=support">Support</a></td></tr>
- <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=contribute">Contribute</a></td></tr>
- <tr><td class="lnav"><a class="nav" href="http://web.enlightenment.org/p.php?p=contact">Contact</a></td></tr>
- <tr><td class="lnav"><a class="nav" href="http://trac.enlightenment.org/e">Tracker</a></td></tr>
- </table>
- </td>
- </tr>
- </table>
-
- <div class="main">
+
+<div id="container">
+
+<div id="header">
+<div class="layout">
+
+ <h1><span>Enlightenment</span></h1>
+ <h2><span>Beauty at your fingertips</span></h2>
+
+ <table cellspacing="0" cellpadding="0" width="100%"><tr>
+ <td id="header_logo">
+ <a href="http://www.enlightenment.org"></a>
+ </td>
+ <td id="header_menu">
+ <table cellspacing="0" cellpadding="0" align="right"><tr>
+ <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=home">Home</a></td>
+ <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=news">News</a></td>
+ <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=about">About</a></td>
+ <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=download">Download</a></td>
+ <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=support">Support</a></td>
+ <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=contribute">Contribute</a></td>
+ <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=contact">Contact</a></td>
+ <td class="nav_passive"><a class="nav_passive" href="http://trac.enlightenment.org/e">Tracker</a></td>
+ <td class="nav_passive"><a class="nav_passive" href="http://www.enlightenment.org/p.php?p=docs">Docs</a></td>
+ </tr></table>
+ </td>
+ <td id="header_last"></td>
+ </tr></table>
+
+ <div class="doxytitle">
+ $projectname Documentation <small>at $date</small>
+ </div>
+
+ <div class="menu-container">
+ <div class="submenu">
+ <ul class="current">
+ <li><a href="files.html">Files</a></li>
+ <li><a href="globals.html">Globals</a></li>
+ <li><a href="modules.html">Modules</a></li>
+ <li><a href="pages.html">Related Pages</a></li>
+ <li class="current"><a href="index.html">Main Page</a></li>
+ </ul>
+ </div>
+ </div>
+
+
+ <div class="clear"></div>
+</div>
+</div>
+
+<div id="content">
+<div class="layout">
--- /dev/null
+/*
+ * 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%;
+}
+
--- /dev/null
+%!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
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
Name: emotion
Description: Emotion evas based multimedia library
-Requires: evas
+@pkgconfig_requires_private@: @requirement_emotion@
Version: @VERSION@
Libs: -L${libdir} -lemotion
-Libs.private: @EDJE_LIBS@ @ECORE_LIBS@ @XINE_LIBS@ @GST_LIBS@
-Cflags: -I${includedir}
+Cflags: -I${includedir}/emotion-@VMAJ@
+%{!?_rel:%{expand:%%global _rel 0.enl%{?dist}}}
%define _missing_doc_files_terminate_build 0
Summary: emotion
%files devel
%defattr(-, root, root)
%doc doc/html
-%{_includedir}/*.h
+%{_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
--- /dev/null
+dnl Copyright (C) 2004-2008 Kim Woelders
+dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+dnl Originally snatched from somewhere...
+
+dnl Macro for checking if the compiler supports __attribute__
+
+dnl Usage: AC_C___ATTRIBUTE__
+dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__
+dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is
+dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused))
+dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is
+dnl defined to nothing.
+
+AC_DEFUN([AC_C___ATTRIBUTE__],
+[
+
+AC_MSG_CHECKING([for __attribute__])
+
+AC_CACHE_VAL([ac_cv___attribute__],
+ [AC_TRY_COMPILE(
+ [
+#include <stdlib.h>
+
+int func(int x);
+int foo(int x __attribute__ ((unused)))
+{
+ exit(1);
+}
+ ],
+ [],
+ [ac_cv___attribute__="yes"],
+ [ac_cv___attribute__="no"]
+ )]
+)
+
+AC_MSG_RESULT($ac_cv___attribute__)
+
+if test "x${ac_cv___attribute__}" = "xyes" ; then
+ AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__])
+ AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused])
+ else
+ AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused])
+fi
+
+])
--- /dev/null
+dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl Macro that check if a binary is built or not
+
+dnl Usage: EFL_ENABLE_BIN(binary[, 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])
+
+])
--- /dev/null
+dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl 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
--- /dev/null
+dnl Copyright (C) 2010-2011 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl Macro that check if 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])
+
+])
--- /dev/null
+dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl 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
--- /dev/null
+dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+
+dnl Macro that check if 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 <sys/mman.h>
+#include <sys/stat.h> /* For mode constants */
+#include <fcntl.h> /* 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 <sys/mman.h>
+#include <sys/stat.h> /* For mode constants */
+#include <fcntl.h> /* 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])
+
+])
--- /dev/null
+
+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])
+])
--- /dev/null
+Name: emotion
+Summary: Media Library
+Version: 1.7.1+svn.76438+build01r01
+Release: 1
+Group: System Environment/Libraries
+License: BSD
+URL: http://www.enlightenment.org/
+Source0: %{name}-%{version}.tar.gz
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+BuildRequires: eina-devel
+BuildRequires: eet-devel
+BuildRequires: evas-devel
+BuildRequires: ecore-devel
+BuildRequires: edje-devel
+BuildRequires: edje-bin
+BuildRequires: gstreamer-devel
+BuildRequires: gst-plugins-base-devel
+
+
+%description
+Video playback library used in Enlightenment DR0.17
+ This is the emotion library, a wrapper library used in the next-generation
+ Enlightenment suite for video playback.
+ .
+ This package contains the shared libraries.
+
+
+%package devel
+Summary: Emotion headers, static libraries, documentation and test programs
+Group: TO_BE/FILLED_IN
+Requires: %{name} = %{version}
+Requires: eet-devel evas-devel edje-devel
+
+
+%description devel
+Headers, static libraries, test programs and documentation for Emotion
+
+
+%package gstreamer
+Summary: Video playback library used in Enlightenment DR0.17
+Group: TO_BE/FILLED_IN
+Requires: %{name} = %{version}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+
+%description gstreamer
+Video playback library used in Enlightenment DR0.17
+This is the emotion library, a wrapper library used in the next-generation
+Enlightenment suite for video playback.
+.
+This package provides the gstreamer module for emotion.
+
+%prep
+%setup -q
+
+%build
+
+%autogen
+%configure --enable-static \
+ --disable-rpath --enable-xine=no --disable-doc
+make %{?jobs:-j%jobs}
+
+
+%install
+rm -rf %{buildroot}
+%make_install
+mkdir -p %{buildroot}/usr/share/license
+cp %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/usr/share/license/%{name}
+
+
+%post -p /sbin/ldconfig
+
+
+%postun -p /sbin/ldconfig
+
+
+%post gstreamer -p /sbin/ldconfig
+
+
+%postun gstreamer -p /sbin/ldconfig
+
+
+%files
+%defattr(-,root,root,-)
+%{_libdir}/libemotion.so.*
+%{_bindir}/emotion_*
+%{_datadir}/emotion/data/*.edj
+%{_libdir}/emotion
+%{_libdir}/edje/modules/emotion/*/module.so
+%manifest %{name}.manifest
+/usr/share/license/%{name}
+%manifest %{name}.manifest
+
+
+%files devel
+%defattr(-, root, root)
+%{_includedir}/*
+%{_libdir}/pkgconfig/emotion*.pc
+%{_libdir}/libemotion.so
+
+
+%files gstreamer
+%defattr(-, root, root)
+%{_libdir}/emotion/*gstreamer*.so
+%manifest %{name}-gstreamer.manifest
MAINTAINERCLEANFILES = Makefile.in
-SUBDIRS = lib bin modules
+SUBDIRS = lib bin modules examples
+
+if ENABLE_EDJE_EXTERNAL
+SUBDIRS += edje_external
+endif
+
+if EMOTION_BUILD_GENERIC
+SUBDIRS += generic_players
+endif
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
-@EVAS_CFLAGS@ \
-@ECORE_CFLAGS@ \
-@EDJE_CFLAGS@
+@EMOTION_CFLAGS@ \
+@EMOTION_CPPFLAGS@ \
+@EMOTION_BIN_CFLAGS@ \
+@ECORE_X_CFLAGS@ \
+@ECORE_FB_CFLAGS@
-bin_PROGRAMS = \
-emotion_test
+bin_PROGRAMS =
-emotion_test_SOURCES = \
-emotion_test_main.c
+if BUILD_EMOTION_TEST
-emotion_test_LDADD = \
-@EVAS_LIBS@ @ECORE_LIBS@ @EDJE_LIBS@ \
-$(top_builddir)/src/lib/libemotion.la
+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
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#if defined(HAVE_ECORE_X_H) || defined(HAVE_ECORE_FB_H)
-
#include <Evas.h>
#include <Ecore.h>
-#ifndef FB_ONLY
-#include <Ecore_X.h>
-#else
-#include <Ecore_Fb.h>
-#endif
+#include <Ecore_Getopt.h>
#include <Ecore_Evas.h>
#include <Edje.h>
#include "Emotion.h"
+static const Ecore_Getopt options = {
+ "emotion_test",
+ "%prog [options] <filename>",
+ "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
Evas_Coord x, y;
};
-static int main_start(int argc, char **argv);
-static void main_stop(void);
static void main_resize(Ecore_Evas *ee);
-static int main_signal_exit(void *data, int ev_type, void *ev);
+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 int startw = 800;
static int starth = 600;
-static Evas_List *video_objs = NULL;
-
-static int
-main_start(int argc, char **argv)
-{
- int mode = 0;
-
- start_time = ecore_time_get();
- if (!ecore_init()) return -1;
- ecore_app_args_set(argc, (const char **)argv);
- ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, NULL);
- if (!ecore_evas_init()) return -1;
-#ifndef FB_ONLY
- {
- int i;
-
- for (i = 1; i < argc; i++)
- {
- if (((!strcmp(argv[i], "-g")) ||
- (!strcmp(argv[i], "-geometry")) ||
- (!strcmp(argv[i], "--geometry"))) && (i < (argc - 1)))
- {
- int n, w, h;
- char buf[16], buf2[16];
-
- n = sscanf(argv[i +1], "%10[^x]x%10s", buf, buf2);
- if (n == 2)
- {
- w = atoi(buf);
- h = atoi(buf2);
- startw = w;
- starth = h;
- }
- i++;
- }
- else if (!strcmp(argv[i], "-gl"))
- {
- mode = 1;
- }
- else if (!strcmp(argv[i], "-fb"))
- {
- mode = 2;
- }
- else if (!strcmp(argv[i], "-xr"))
- {
- mode = 3;
- }
- }
- }
-#if HAVE_ECORE_EVAS_X
- if (mode == 0)
- ecore_evas = ecore_evas_software_x11_new(NULL, 0, 0, 0, startw, starth);
-#endif
-#if HAVE_ECORE_EVAS_X11_GL
- if (mode == 1)
- ecore_evas = ecore_evas_gl_x11_new(NULL, 0, 0, 0, startw, starth);
-#endif
-#if HAVE_ECORE_EVAS_FB
- if (mode == 2)
- ecore_evas = ecore_evas_fb_new(NULL, 0, startw, starth);
-#endif
- if (mode == 3)
- ecore_evas = ecore_evas_xrender_x11_new(NULL, 0, 0, 0, startw, starth);
-
-#else
- startw = 240;
- starth = 320;
- ecore_evas = ecore_evas_fb_new(NULL, 270, startw, starth);
-#endif
- if (!ecore_evas) return -1;
- 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");
-
- edje_init();
- edje_frametime_set(1.0 / 30.0);
- return 1;
-}
-
-static void
-main_stop(void)
-{
- main_signal_exit(NULL, 0, NULL);
- edje_shutdown();
- ecore_evas_shutdown();
- ecore_shutdown();
-}
+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(evas, NULL, NULL, &w, &h);
+ evas_output_viewport_get(ecore_evas_get(ee), NULL, NULL, &w, &h);
bg_resize(w, h);
}
-static int
-main_signal_exit(void *data, int ev_type, void *ev)
+static Eina_Bool
+main_signal_exit(void *data __UNUSED__, int ev_type __UNUSED__, void *ev __UNUSED__)
{
+ Evas_Object *o;
+
ecore_main_loop_quit();
- while (video_objs)
+ EINA_LIST_FREE(video_objs, o)
{
- printf("del obj!\n");
- evas_object_del(video_objs->data);
- video_objs = evas_list_remove_list(video_objs, video_objs);
- printf("done\n");
+ emotion_object_last_position_save(o);
+ evas_object_del(o);
}
- return 1;
+ return EINA_TRUE;
}
static void
-main_delete_request(Ecore_Evas *ee)
+main_delete_request(Ecore_Evas *ee __UNUSED__)
{
ecore_main_loop_quit();
}
static void
broadcast_event(Emotion_Event ev)
{
- Evas_List *l;
-
- for (l = video_objs; l; l = l->next)
- {
- Evas_Object *obj;
+ Eina_List *l;
+ Evas_Object *obj;
- obj = l->data;
- emotion_object_event_simple_send(obj, ev);
- }
+ EINA_LIST_FOREACH(video_objs, l, obj)
+ emotion_object_event_simple_send(obj, ev);
}
static void
-bg_key_down(void *data, Evas * e, Evas_Object * obj, void *event_info)
+bg_key_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
{
- Evas_Event_Key_Down *ev;
+ Evas_Event_Key_Down *ev = event_info;
+ Eina_List *l;
+ Evas_Object *o;
- ev = (Evas_Event_Key_Down *)event_info;
if (!strcmp(ev->keyname, "Escape"))
ecore_main_loop_quit();
else if (!strcmp(ev->keyname, "Up"))
broadcast_event(EMOTION_EVENT_10);
else if (!strcmp(ev->keyname, "bracketleft"))
{
- Evas_List *l;
-
- for (l = video_objs; l; l = l->next)
- {
- Evas_Object *obj;
-
- obj = l->data;
- emotion_object_audio_volume_set(obj, emotion_object_audio_volume_get(obj) - 0.1);
- }
+ 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"))
{
- Evas_List *l;
-
- for (l = video_objs; l; l = l->next)
- {
- Evas_Object *obj;
-
- obj = l->data;
- emotion_object_audio_volume_set(obj, emotion_object_audio_volume_get(obj) + 0.1);
- }
+ 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"))
{
- Evas_List *l;
-
- for (l = video_objs; l; l = l->next)
+ EINA_LIST_FOREACH(video_objs, l, o)
{
- Evas_Object *obj;
-
- obj = l->data;
- if (emotion_object_video_mute_get(obj))
- emotion_object_video_mute_set(obj, 0);
+ if (emotion_object_video_mute_get(o))
+ emotion_object_video_mute_set(o, 0);
else
- emotion_object_video_mute_set(obj, 1);
+ emotion_object_video_mute_set(o, 1);
}
}
else if (!strcmp(ev->keyname, "a"))
{
- Evas_List *l;
-
- for (l = video_objs; l; l = l->next)
+ EINA_LIST_FOREACH(video_objs, l, o)
{
- Evas_Object *obj;
-
- obj = l->data;
- if (emotion_object_audio_mute_get(obj))
+ if (emotion_object_audio_mute_get(o))
{
- emotion_object_audio_mute_set(obj, 0);
+ emotion_object_audio_mute_set(o, 0);
printf("unmute\n");
}
else
{
- emotion_object_audio_mute_set(obj, 1);
+ emotion_object_audio_mute_set(o, 1);
printf("mute\n");
}
}
}
else if (!strcmp(ev->keyname, "i"))
{
- Evas_List *l;
-
- for (l = video_objs; l; l = l->next)
+ EINA_LIST_FOREACH(video_objs, l, o)
{
- Evas_Object *obj;
-
- obj = l->data;
- printf("audio channels: %i\n", emotion_object_audio_channel_count(obj));
- printf("video channels: %i\n", emotion_object_video_channel_count(obj));
- printf("spu channels: %i\n", emotion_object_spu_channel_count(obj));
- printf("seekable: %i\n", emotion_object_seekable_get(obj));
+ 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"))
{
printf("del obj!\n");
evas_object_del(video_objs->data);
- video_objs = evas_list_remove_list(video_objs, video_objs);
+ video_objs = eina_list_remove_list(video_objs, video_objs);
printf("done\n");
}
}
- else
+ else if (!strcmp(ev->keyname, "z"))
{
- printf("UNHANDLED: %s\n", ev->keyname);
- }
-}
-
-static void
-video_obj_in_cb(void *data, Evas *ev, Evas_Object *obj, void *event_info)
-{
-// evas_object_color_set(obj, 255, 255, 255, 100);
-}
-
-static void
-video_obj_out_cb(void *data, Evas *ev, Evas_Object *obj, void *event_info)
-{
-// evas_object_color_set(obj, 255, 255, 255, 200);
-}
-
-static void
-video_obj_down_cb(void *data, Evas *ev, Evas_Object *obj, void *event_info)
-{
- Evas_Event_Mouse_Down *e;
-
- e = event_info;
- evas_object_color_set(obj, 200, 50, 40, 200);
- evas_object_raise(obj);
-}
+ vis = (vis + 1) % EMOTION_VIS_LAST;
+ printf("new visualization: %d\n", vis);
-static void
-video_obj_up_cb(void *data, Evas *ev, Evas_Object *obj, void *event_info)
-{
- Evas_Event_Mouse_Up *e;
-
- e = event_info;
- evas_object_color_set(obj, 100, 100, 100, 100);
-}
-
-static void
-video_obj_move_cb(void *data, Evas *ev, Evas_Object *obj, void *event_info)
-{
- Evas_Event_Mouse_Move *e;
+ EINA_LIST_FOREACH(video_objs, l, o)
+ {
+ Eina_Bool supported;
- e = event_info;
- if (e->buttons & 0x1)
- {
- Evas_Coord x, y;
+ supported = emotion_object_vis_supported(o, vis);
+ if (supported)
+ emotion_object_vis_set(o, vis);
+ else
+ {
+ const char *file;
- evas_object_geometry_get(obj, &x, &y, NULL, NULL);
- x += e->cur.canvas.x - e->prev.canvas.x;
- y += e->cur.canvas.y - e->prev.canvas.y;
- evas_object_move(obj, x, y);
+ file = emotion_object_file_get(o);
+ printf("object %p (%s) does not support visualization %d\n",
+ o, file, vis);
+ }
+ }
}
- else if (e->buttons & 0x4)
+ else
{
- Evas_Coord w, h;
-
- evas_object_geometry_get(obj, NULL, NULL, &w, &h);
- w += e->cur.canvas.x - e->prev.canvas.x;
- h += e->cur.canvas.y - e->prev.canvas.y;
- evas_object_resize(obj, w, h);
+ printf("UNHANDLED: %s\n", ev->keyname);
}
}
static void
-video_obj_frame_decode_cb(void *data, Evas_Object *obj, void *event_info)
+video_obj_time_changed(Evas_Object *obj, Evas_Object *edje)
{
- Evas_Object *oe;
- double pos, len;
+ double pos, len, scale;
char buf[256];
int ph, pm, ps, pf, lh, lm, ls;
- oe = data;
pos = emotion_object_position_get(obj);
len = emotion_object_play_length_get(obj);
-// printf("%3.3f, %3.3f\n", pos, len);
- edje_object_part_drag_value_set(oe, "video_progress", pos / len, 0.0);
+ 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);
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(oe, "video_progress_txt", buf);
+ 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)
{
}
static void
-video_obj_frame_resize_cb(void *data, Evas_Object *obj, void *event_info)
+video_obj_frame_resize_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
{
Evas_Object *oe;
int iw, ih;
}
static void
-video_obj_length_change_cb(void *data, Evas_Object *obj, void *event_info)
+video_obj_length_change_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
{
- Evas_Object *oe;
- double pos, len;
- char buf[256];
- int ph, pm, ps, pf, lh, lm, ls;
-
- oe = data;
- pos = emotion_object_position_get(obj);
- len = emotion_object_play_length_get(obj);
- edje_object_part_drag_value_set(oe, "video_progress", pos / len, 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(oe, "video_progress_txt", buf);
+ video_obj_time_changed(obj, data);
}
static void
-video_obj_stopped_cb(void *data, Evas_Object *obj, void *event_info)
+video_obj_position_update_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
{
- Evas_Object *oe;
+ video_obj_time_changed(obj, data);
+}
- oe = 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, Evas_Object *obj, void *event_info)
+video_obj_channels_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
{
- Evas_Object *oe;
-
- oe = data;
printf("channels changed: [AUD %i][VID %i][SPU %i]\n",
emotion_object_audio_channel_count(obj),
emotion_object_video_channel_count(obj),
}
static void
-video_obj_title_cb(void *data, Evas_Object *obj, void *event_info)
+video_obj_title_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
{
- Evas_Object *oe;
-
- oe = data;
printf("video title to: \"%s\"\n", emotion_object_title_get(obj));
}
static void
-video_obj_progress_cb(void *data, Evas_Object *obj, void *event_info)
+video_obj_progress_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
{
- Evas_Object *oe;
-
- oe = data;
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, Evas_Object *obj, void *event_info)
+video_obj_ref_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
{
- Evas_Object *oe;
-
- oe = data;
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, Evas_Object *obj, void *event_info)
+video_obj_button_num_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
{
- Evas_Object *oe;
-
- oe = data;
printf("video spu buttons to: %i\n",
emotion_object_spu_button_count_get(obj));
}
static void
-video_obj_button_cb(void *data, Evas_Object *obj, void *event_info)
+video_obj_button_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
{
- Evas_Object *oe;
-
- oe = data;
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, const char *source)
+video_obj_signal_play_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__)
{
- Evas_Object *ov;
-
- ov = data;
+ 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, const char *source)
+video_obj_signal_pause_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__)
{
- Evas_Object *ov;
-
- ov = data;
+ 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, const char *source)
+video_obj_signal_stop_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__)
{
- Evas_Object *ov;
-
- ov = data;
+ 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, const char *source)
+video_obj_signal_jump_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__)
{
- Evas_Object *ov;
+ Evas_Object *ov = data;
double len;
double x, y;
- ov = data;
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, const char *source)
+video_obj_signal_speed_cb(void *data, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__)
{
- Evas_Object *ov;
+ Evas_Object *ov = data;
double spd;
double x, y;
char buf[256];
- ov = data;
edje_object_part_drag_value_get(o, source, &x, &y);
spd = 255 * y;
evas_object_color_set(ov, spd, spd, spd, spd);
}
static void
-video_obj_signal_frame_move_start_cb(void *data, Evas_Object *o, const char *emission, const char *source)
+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;
}
static void
-video_obj_signal_frame_move_stop_cb(void *data, Evas_Object *o, const char *emission, const char *source)
+video_obj_signal_frame_move_stop_cb(void *data __UNUSED__, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__)
{
Frame_Data *fd;
}
static void
-video_obj_signal_frame_resize_start_cb(void *data, Evas_Object *o, const char *emission, const char *source)
+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;
}
static void
-video_obj_signal_frame_resize_stop_cb(void *data, Evas_Object *o, const char *emission, const char *source)
+video_obj_signal_frame_resize_stop_cb(void *data __UNUSED__, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__)
{
Frame_Data *fd;
}
static void
-video_obj_signal_frame_move_cb(void *data, Evas_Object *o, const char *emission, const char *source)
+video_obj_signal_frame_move_cb(void *data __UNUSED__, Evas_Object *o, const char *emission __UNUSED__, const char *source __UNUSED__)
{
Frame_Data *fd;
static void
-init_video_object(char *module_filename, char *filename)
+init_video_object(const char *module_filename, const char *filename)
{
Evas_Object *o, *oe;
int iw, ih;
o = emotion_object_add(evas);
if (!emotion_object_init(o, module_filename))
return;
- emotion_object_file_set(o, filename);
+ 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);
/* end basic video setup. all the rest here is just to be fancy */
- video_objs = evas_list_append(video_objs, o);
+ video_objs = eina_list_append(video_objs, o);
emotion_object_size_get(o, &iw, &ih);
w = iw; h = ih;
oe = edje_object_add(evas);
evas_object_data_set(oe, "frame_data", fd);
- edje_object_file_set(oe, PACKAGE_DATA_DIR"/data/theme.edj", "video_controller");
+ 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_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_show(oe);
}
-static int
-enter_idle(void *data)
+static Eina_Bool
+check_positions(void *data __UNUSED__)
{
- double t;
- static double pt = 0.0;
- static int frames = 0;
+ const Eina_List *lst;
+ Evas_Object *o;
- t = ecore_time_get();
- if (frames == 0) pt = t;
- frames++;
- if (frames == 100)
- {
-// printf("FPS: %3.3f\n", frames / (t - pt));
- frames = 0;
- }
- return 1;
+ 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)
{
- char *module_filename;
- int i;
+ 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;
- if (main_start(argc, argv) < 1) return -1;
- bg_setup();
+ start_time = ecore_time_get();
+ ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, NULL);
+ edje_frametime_set(1.0 / 30.0);
- module_filename = "xine";
+ 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;
+ }
- for (i = 1; i < argc; i++)
+ if ((geometry.w == 0) || (geometry.h == 0))
{
- if (((!strcmp(argv[i], "-g")) ||
- (!strcmp(argv[i], "-geometry")) ||
- (!strcmp(argv[i], "--geometry"))) && (i < (argc - 1)))
- i++;
- else if (((!strcmp(argv[i], "-h")) ||
- (!strcmp(argv[i], "-help")) ||
- (!strcmp(argv[i], "--help"))))
- {
- printf("Usage:\n");
- printf(" %s [-gl] [-g WxH] [-xine] [-gstreamer] filename\n", argv[0]);
- exit(-1);
- }
- else if (!strcmp(argv[i], "-gl"))
- {
- }
- else if (!strcmp(argv[i], "-fb"))
- {
- }
- else if (!strcmp(argv[i], "-xr"))
- {
- }
- else if (!strcmp(argv[i], "-xine"))
- {
- module_filename = "xine";
- }
- else if (!strcmp(argv[i], "-gstreamer"))
- {
- module_filename = "gstreamer";
- }
- else
- {
- printf ("module : %s\n", module_filename);
- init_video_object(module_filename, argv[i]);
- }
+ if (geometry.w == 0) geometry.w = 320;
+ if (geometry.h == 0) geometry.h = 240;
}
- ecore_idle_enterer_add(enter_idle, NULL);
+ printf("evas engine: %s\n", engine ? engine : "<auto>");
+ printf("emotion backend: %s\n", backend ? backend : "<auto>");
+ 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_stop();
+
+ main_signal_exit(NULL, 0, NULL);
+
+ emotion_shutdown();
+ ecore_evas_free(ecore_evas);
+ ecore_evas_shutdown();
+ edje_shutdown();
+
return 0;
-}
-#else
-int main()
-{
- puts("Could not find Ecore_X.h or Ecore_Fb.h so test is disabled");
- return 0;
+ shutdown_edje:
+ edje_shutdown();
+ shutdown_ecore_evas:
+ ecore_evas_shutdown();
+
+ return -1;
}
-#endif
--- /dev/null
+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
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Edje.h>
+
+#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);
--- /dev/null
+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
+
--- /dev/null
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <stdio.h>
+
+#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 <filename>\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;
+}
--- /dev/null
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <filename>\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;
+}
--- /dev/null
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#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 <filename>\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;
+}
--- /dev/null
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Emotion.h>
+#include <stdio.h>
+
+#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 <filename> [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;
+}
--- /dev/null
+
+MAINTAINERCLEANFILES = Makefile.in
+
+SUBDIRS =
+
+if EMOTION_BUILD_GENERIC_VLC
+SUBDIRS += vlc
+endif
--- /dev/null
+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
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <poll.h>
+
+#include <sys/prctl.h>
+#include <signal.h>
+
+#include <vlc/vlc.h>
+
+#include <Emotion_Generic_Plugin.h>
+
+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 <fd read> <fd write>\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
#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 <raster@rasterman.com>
+ * @author Vincent Torri <torri@maths.univ-evry.fr>
+ * @author Nicolas Aguirre <aguirre.nicolas@gmail.com>
+ * @author Sebastian Dransfeld <sd@tango.flipp.net>
+ * @author Cedric Bail <cedric.bail@free.fr>
+ *
+ * Please contact <enlightenment-devel@lists.sourceforge.net> to get in
+ * contact with the developers and maintainers.
+ *
+ */
+
+#include <Evas.h>
+
#ifdef EAPI
-#undef EAPI
+# undef EAPI
#endif
-#ifdef WIN32
-# ifdef BUILDING_DLL
-# define EAPI __declspec(dllexport)
+
+#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
+# endif /* ! EFL_EMOTION_BUILD */
#else
# ifdef __GNUC__
# if __GNUC__ >= 4
# else
# define EAPI
# endif
-#endif
+#endif /* ! _WIN32 */
-#include <Evas.h>
+/**
+ * @file Emotion.h
+ * @brief The file that provides Emotion the API, with functions available for
+ * play, seek, change volume, etc.
+ */
enum _Emotion_Module
{
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,
- EMOTION_META_INFO_TRACK_ARTIST,
- EMOTION_META_INFO_TRACK_ALBUM,
- EMOTION_META_INFO_TRACK_YEAR,
- EMOTION_META_INFO_TRACK_GENRE,
- EMOTION_META_INFO_TRACK_COMMENT,
- EMOTION_META_INFO_TRACK_DISC_ID,
- EMOTION_META_INFO_TRACK_COUNT
+ 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;
+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 8
+
+ 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);
-EAPI Evas_Bool emotion_object_init (Evas_Object *obj, const char *module_filename);
-EAPI void emotion_object_file_set (Evas_Object *obj, const char *filename);
-EAPI const char *emotion_object_file_get (Evas_Object *obj);
-EAPI void emotion_object_play_set (Evas_Object *obj, Evas_Bool play);
-EAPI Evas_Bool emotion_object_play_get (Evas_Object *obj);
+
+/**
+ * @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);
-EAPI double emotion_object_position_get (Evas_Object *obj);
-EAPI Evas_Bool emotion_object_video_handled_get (Evas_Object *obj);
-EAPI Evas_Bool emotion_object_audio_handled_get (Evas_Object *obj);
-EAPI Evas_Bool emotion_object_seekable_get (Evas_Object *obj);
-EAPI double emotion_object_play_length_get (Evas_Object *obj);
-EAPI void emotion_object_size_get (Evas_Object *obj, int *iw, int *ih);
-EAPI void emotion_object_smooth_scale_set (Evas_Object *obj, Evas_Bool smooth);
-EAPI Evas_Bool emotion_object_smooth_scale_get (Evas_Object *obj);
-EAPI double emotion_object_ratio_get (Evas_Object *obj);
+/**
+ * @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);
-EAPI double emotion_object_audio_volume_get (Evas_Object *obj);
-EAPI void emotion_object_audio_mute_set (Evas_Object *obj, Evas_Bool mute);
-EAPI Evas_Bool emotion_object_audio_mute_get (Evas_Object *obj);
-EAPI int emotion_object_audio_channel_count (Evas_Object *obj);
-EAPI const char *emotion_object_audio_channel_name_get(Evas_Object *obj, int channel);
+
+/**
+ * @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 (Evas_Object *obj);
-EAPI void emotion_object_video_mute_set (Evas_Object *obj, Evas_Bool mute);
-EAPI Evas_Bool emotion_object_video_mute_get (Evas_Object *obj);
-EAPI int emotion_object_video_channel_count (Evas_Object *obj);
-EAPI const char *emotion_object_video_channel_name_get(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 (Evas_Object *obj);
-EAPI void emotion_object_spu_mute_set (Evas_Object *obj, Evas_Bool mute);
-EAPI Evas_Bool emotion_object_spu_mute_get (Evas_Object *obj);
-EAPI int emotion_object_spu_channel_count (Evas_Object *obj);
-EAPI const char *emotion_object_spu_channel_name_get (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 (Evas_Object *obj);
-EAPI int emotion_object_chapter_count (Evas_Object *obj);
+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 (Evas_Object *obj);
-EAPI const char *emotion_object_chapter_name_get (Evas_Object *obj, int chapter);
-EAPI void emotion_object_play_speed_set (Evas_Object *obj, double speed);
-EAPI double emotion_object_play_speed_get (Evas_Object *obj);
+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);
-EAPI const char *emotion_object_title_get (Evas_Object *obj);
-EAPI const char *emotion_object_progress_info_get (Evas_Object *obj);
-EAPI double emotion_object_progress_status_get (Evas_Object *obj);
-EAPI const char *emotion_object_ref_file_get (Evas_Object *obj);
-EAPI int emotion_object_ref_num_get (Evas_Object *obj);
-EAPI int emotion_object_spu_button_count_get (Evas_Object *obj);
-EAPI int emotion_object_spu_button_get (Evas_Object *obj);
-EAPI const char *emotion_object_meta_info_get (Evas_Object *obj, Emotion_Meta_Info meta);
+
+/**
+ * @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
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
-@EVAS_CFLAGS@ \
-@ECORE_CFLAGS@
+@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
-include_HEADERS = Emotion.h
-libemotion_la_SOURCES = \
-emotion_smart.c \
-emotion_private.h
-
-libemotion_la_LIBADD = @EVAS_LIBS@ @ECORE_LIBS@
-libemotion_la_DEPENDENCIES = $(top_builddir)/config.h
-libemotion_la_LDFLAGS = -version-info @version_info@
+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
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#elif !defined alloca
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# elif defined _AIX
+# define alloca __alloca
+# elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# elif !defined HAVE_ALLOCA
+# ifdef __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+# endif
+#endif
+
+#include <stdio.h>
+
+#ifdef EMOTION_HAVE_EEZE
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <sys/ioctl.h>
+# ifdef HAVE_V4L2
+# include <linux/videodev2.h>
+# endif
+
+# include <Ecore.h>
+# include <Eeze.h>
+#endif
+
+#include <Eet.h>
+
+#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--;
+}
#ifndef EMOTION_PRIVATE_H
#define EMOTION_PRIVATE_H
-#include <Evas.h>
-#include <Ecore.h>
-#include <Ecore_Job.h>
-#include <Ecore_Data.h>
-#include <Ecore_Str.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "config.h"
-
#define META_TRACK_TITLE 1
#define META_TRACK_ARTIST 2
#define META_TRACK_GENRE 3
#define META_TRACK_COUNT 8
typedef enum _Emotion_Format Emotion_Format;
-typedef enum _Emotion_Vis Emotion_Vis;
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_BGRA
};
-enum _Emotion_Vis
+struct _Emotion_Module_Options
{
- EMOTION_VIS_GOOM,
- EMOTION_VIS_LIBVISUAL_BUMPSCOPE,
- EMOTION_VIS_LIBVISUAL_CORONA,
- EMOTION_VIS_LIBVISUAL_DANCING_PARTICLES,
- EMOTION_VIS_LIBVISUAL_GDKPIXBUF,
- EMOTION_VIS_LIBVISUAL_G_FORCE,
- EMOTION_VIS_LIBVISUAL_GOOM,
- EMOTION_VIS_LIBVISUAL_INFINITE,
- EMOTION_VIS_LIBVISUAL_JAKDAW,
- EMOTION_VIS_LIBVISUAL_JESS,
- EMOTION_VIS_LIBVISUAL_LV_ANALYSER,
- EMOTION_VIS_LIBVISUAL_LV_FLOWER,
- EMOTION_VIS_LIBVISUAL_LV_GLTEST,
- EMOTION_VIS_LIBVISUAL_LV_SCOPE,
- EMOTION_VIS_LIBVISUAL_MADSPIN,
- EMOTION_VIS_LIBVISUAL_NEBULUS,
- EMOTION_VIS_LIBVISUAL_OINKSIE,
- EMOTION_VIS_LIBVISUAL_PLASMA
+ const char *player;
+ Eina_Bool no_video : 1;
+ Eina_Bool no_audio : 1;
};
-struct _Emotion_Module_Options
+struct _Eina_Emotion_Plugins
{
- unsigned char no_video : 1;
- unsigned char no_audio : 1;
+ Emotion_Module_Open open;
+ Emotion_Module_Close close;
};
struct _Emotion_Video_Module
void (*stop) (void *ef);
void (*size_get) (void *ef, int *w, int *h);
void (*pos_set) (void *ef, double pos);
- void (*vis_set) (void *ef, Emotion_Vis vis);
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);
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);
- Ecore_Plugin *plugin;
- Ecore_Path_Group *path_group;
+ Eina_Emotion_Plugins *plugin;
};
-EAPI void *_emotion_video_get(Evas_Object *obj);
+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, char *file, int num);
+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
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Evas.h>
+#include <Ecore.h>
+
+#ifdef HAVE_EIO
+# include <math.h>
+# include <Eio.h>
+#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 (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;
+ void *video_data;
char *module_name;
- char *file;
+ const char *file;
Evas_Object *obj;
- double ratio;
- double pos;
- double seek_pos;
- double len;
+ Evas_Object *bg;
Ecore_Job *job;
- unsigned char play : 1;
- unsigned char seek : 1;
-
char *title;
+
+#ifdef HAVE_EIO
+ Eio_File *load_xattr;
+ Eio_File *save_xattr;
+#endif
+
struct {
char *info;
double stat;
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);
/* Globals for the E Video Object */
/**********************************/
static Evas_Smart *smart = NULL;
-static Ecore_Path_Group *path_group = 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;
-static unsigned char
+ 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)
{
- Ecore_Plugin *plugin;
- char *tmp = NULL;
+ Eina_Emotion_Plugins *plugin;
Smart_Data *sd;
+ unsigned int i = 0;
E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
- if (!path_group)
- path_group = ecore_path_group_new();
- tmp = getenv("EMOTION_MODULES_DIR");
- if (tmp)
- ecore_path_group_add(path_group, tmp);
- ecore_path_group_add(path_group, PACKAGE_LIB_DIR"/emotion/");
- plugin = ecore_plugin_load(path_group, name, NULL);
- if (plugin)
+ if (!_backends)
{
- unsigned char (*func_module_open)(Evas_Object *, Emotion_Video_Module **, void **, Emotion_Module_Options *);
+ ERR("No backend loaded");
+ return NULL;
+ }
- func_module_open = ecore_plugin_symbol_get(plugin, "module_open");
- if (func_module_open)
- {
- if (func_module_open(obj, mod, video, &(sd->module_options)))
- {
- if (*mod)
- {
- (*mod)->plugin = plugin;
- (*mod)->path_group = path_group;
- return 1;
- }
- }
- }
- ecore_plugin_unload(plugin);
+ 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;
}
- else
- printf ("Unable to load module %s\n", name);
- if (path_group)
+ if (plugin->open(obj, (const Emotion_Video_Module **) mod, video, &(sd->module_options)))
{
- ecore_path_group_del(path_group);
- path_group = NULL;
+ if (*mod)
+ {
+ (*mod)->plugin = plugin;
+ return name;
+ }
}
- return 0;
+ if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*)))
+ goto retry;
+
+ ERR("Unable to load module: %s", name);
+
+ return NULL;
}
static void
-_emotion_module_close(Emotion_Video_Module *mod, void *video)
+_clipper_position_size_update(Evas_Object *obj, int x, int y, int w, int h, int vid_w, int vid_h)
{
- Ecore_Plugin *plugin;
- void (*module_close) (Emotion_Video_Module *module, void *);
+ Smart_Data *sd;
+ double scale_w, scale_h;
- plugin = mod->plugin;
- module_close = ecore_plugin_symbol_get(mod->plugin, "module_close");
- if ((module_close) && (video)) module_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 shouldnt be too bad and
- * mean that once a module is dlopened() it cant be closed - its refcount
- * will just keep going up
- */
- /*
- ecore_plugin_unload(plugin);
- */
- if (path_group)
+ E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+
+ if (vid_w == 0 || vid_h == 0)
{
- ecore_path_group_del(path_group);
- path_group = NULL;
+ 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);
}
}
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)
{
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
if ((!opt) || (!val)) return;
- if (!strcmp(opt, "video"))
- {
- if (!strcmp(val, "off")) sd->module_options.no_video = 1;
- }
- else if (!strcmp(opt, "audio"))
- {
- if (!strcmp(val, "off")) sd->module_options.no_audio = 1;
- }
+
+ if (!strcmp(opt, "player"))
+ eina_stringshare_replace(&sd->module_options.player, val);
}
-EAPI Evas_Bool
+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->file) free(sd->file);
+ 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;
- if (sd->title) free(sd->title);
+
+ free(sd->title);
sd->title = NULL;
- if (sd->progress.info) free(sd->progress.info);
+ free(sd->progress.info);
sd->progress.info = NULL;
sd->progress.stat = 0.0;
- if (sd->ref.file) free(sd->ref.file);
+ 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;
- ecore_job_init();
+ _emotion_module_close(sd->module, sd->video_data);
+ sd->module = NULL;
+ sd->video_data = NULL;
- if ((!sd->module) || (!sd->video))
+ 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)
{
- if (!_emotion_module_open(module_filename, obj,
- &sd->module, &sd->video))
- return 0;
+ emotion_object_file_set(obj, file);
+ eina_stringshare_del(file);
}
- return 1;
+ return EINA_TRUE;
}
-EAPI void
+EAPI Eina_Bool
emotion_object_file_set(Evas_Object *obj, const char *file)
{
Smart_Data *sd;
- E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+ E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EINA_FALSE);
+
+ DBG("file=%s", file);
+ if (!sd->module) return EINA_FALSE;
- if ((file) && (sd->file) && (!strcmp(file, sd->file))) return;
+ 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))
{
- int w, h;
-
- if (sd->file) free(sd->file);
- sd->file = strdup(file);
- if (sd->module)
- {
- sd->module->file_close(sd->video);
- evas_object_image_size_set(sd->obj, 0, 0);
- }
- if (!sd->module->file_open(sd->file, obj, sd->video))
- return;
- sd->module->size_get(sd->video, &w, &h);
- evas_object_image_size_set(sd->obj, w, h);
- sd->ratio = sd->module->ratio_get(sd->video);
+ 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, 0.0);
+ if (sd->play) sd->module->play(sd->video_data, 0.0);
}
else
{
- if (sd->video && sd->module)
+ if (sd->video_data && sd->module)
{
- sd->module->file_close(sd->video);
- evas_object_image_size_set(sd->obj, 0, 0);
+ 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);
}
- if (sd->file) free(sd->file);
- sd->file = NULL;
+ 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(Evas_Object *obj)
+emotion_object_file_get(const Evas_Object *obj)
{
Smart_Data *sd;
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, Evas_Bool play)
+emotion_object_play_set(Evas_Object *obj, Eina_Bool play)
{
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
- if (((play) && (sd->play)) || ((!play) && (!sd->play))) return;
+ DBG("play=" FMT_UCHAR ", was=" FMT_UCHAR, play, sd->play);
+ if (play == sd->play) return;
if (!sd->module) return;
- if (!sd->video) return;
+ if (!sd->video_data) return;
+ if (!sd->open)
+ {
+ sd->remember_play = play;
+ return;
+ }
sd->play = play;
- if (sd->play) sd->module->play(sd->video, sd->pos);
- else sd->module->stop(sd->video);
+ 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 Evas_Bool
-emotion_object_play_get(Evas_Object *obj)
+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) return 0;
+ if (!sd->video_data) return EINA_FALSE;
return sd->play;
}
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+ DBG("sec=%f", sec);
if (!sd->module) return;
- if (!sd->video) 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;
}
EAPI double
-emotion_object_position_get(Evas_Object *obj)
+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) 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 Evas_Bool
-emotion_object_seekable_get(Evas_Object *obj)
+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 0;
- if (!sd->video) return 0;
- return sd->module->seekable(sd->video);
+ if (!sd->module) return EINA_FALSE;
+ if (!sd->video_data) return EINA_FALSE;
+ return sd->module->seekable(sd->video_data);
}
-EAPI Evas_Bool
-emotion_object_video_handled_get(Evas_Object *obj)
+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 0;
- if (!sd->video) return 0;
- return sd->module->video_handled(sd->video);
+ if (!sd->module) return EINA_FALSE;
+ if (!sd->video_data) return EINA_FALSE;
+ return sd->module->video_handled(sd->video_data);
}
-EAPI Evas_Bool
-emotion_object_audio_handled_get(Evas_Object *obj)
+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 0;
- if (!sd->video) return 0;
- return sd->module->audio_handled(sd->video);
+ 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(Evas_Object *obj)
+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) return 0.0;
- sd->len = sd->module->len_get(sd->video);
+ 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(Evas_Object *obj, int *iw, int *ih)
+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);
- evas_object_image_size_get(sd->obj, iw, ih);
+ if (iw) *iw = sd->video.w;
+ if (ih) *ih = sd->video.h;
}
EAPI void
-emotion_object_smooth_scale_set(Evas_Object *obj, Evas_Bool smooth)
+emotion_object_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth)
{
Smart_Data *sd;
evas_object_image_smooth_scale_set(sd->obj, smooth);
}
-EAPI Evas_Bool
-emotion_object_smooth_scale_get(Evas_Object *obj)
+EAPI Eina_Bool
+emotion_object_smooth_scale_get(const Evas_Object *obj)
{
Smart_Data *sd;
}
EAPI double
-emotion_object_ratio_get(Evas_Object *obj)
+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) 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)
{
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
if (!sd->module) return;
- if (!sd->video) return;
- sd->module->event_feed(sd->video, ev);
+ if (!sd->video_data) return;
+ sd->module->event_feed(sd->video_data, ev);
}
EAPI void
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+ DBG("vol=%f", vol);
if (!sd->module) return;
- if (!sd->video) return;
- sd->module->audio_channel_volume_set(sd->video, vol);
+ if (!sd->video_data) return;
+ sd->module->audio_channel_volume_set(sd->video_data, vol);
}
EAPI double
-emotion_object_audio_volume_get(Evas_Object *obj)
+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) return 0.0;
- return sd->module->audio_channel_volume_get(sd->video);
+ 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, Evas_Bool mute)
+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) return;
- sd->module->audio_channel_mute_set(sd->video, mute);
+ if (!sd->video_data) return;
+ sd->module->audio_channel_mute_set(sd->video_data, mute);
}
-EAPI Evas_Bool
-emotion_object_audio_mute_get(Evas_Object *obj)
+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 0;
- if (!sd->video) return 0;
- return sd->module->audio_channel_mute_get(sd->video);
+ 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(Evas_Object *obj)
+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) return 0;
- return sd->module->audio_channel_count(sd->video);
+ if (!sd->video_data) return 0;
+ return sd->module->audio_channel_count(sd->video_data);
}
EAPI const char *
-emotion_object_audio_channel_name_get(Evas_Object *obj, int channel)
+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) return NULL;
- return sd->module->audio_channel_name_get(sd->video, channel);
+ if (!sd->video_data) return NULL;
+ return sd->module->audio_channel_name_get(sd->video_data, channel);
}
EAPI void
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+ DBG("channel=%d", channel);
if (!sd->module) return;
- if (!sd->video) return;
- sd->module->audio_channel_set(sd->video, channel);
+ if (!sd->video_data) return;
+ sd->module->audio_channel_set(sd->video_data, channel);
}
EAPI int
-emotion_object_audio_channel_get(Evas_Object *obj)
+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) return 0;
- return sd->module->audio_channel_get(sd->video);
+ 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, Evas_Bool mute)
+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) return;
- sd->module->video_channel_mute_set(sd->video, mute);
+ if (!sd->video_data) return;
+ sd->module->video_channel_mute_set(sd->video_data, mute);
}
-EAPI Evas_Bool
-emotion_object_video_mute_get(Evas_Object *obj)
+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 0;
- if (!sd->video) return 0;
- return sd->module->video_channel_mute_get(sd->video);
+ 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(Evas_Object *obj)
+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 0;
- if (!sd->video) return 0;
- return sd->module->video_channel_count(sd->video);
+ 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(Evas_Object *obj, int channel)
+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) return NULL;
- return sd->module->video_channel_name_get(sd->video, channel);
+ if (!sd->video_data) return NULL;
+ return sd->module->video_channel_name_get(sd->video_data, channel);
}
EAPI void
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+ DBG("channel=%d", channel);
if (!sd->module) return;
- if (!sd->video) return;
- sd->module->video_channel_set(sd->video, channel);
+ if (!sd->video_data) return;
+ sd->module->video_channel_set(sd->video_data, channel);
}
EAPI int
-emotion_object_video_channel_get(Evas_Object *obj)
+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) return 0;
- return sd->module->video_channel_get(sd->video);
+ 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, Evas_Bool mute)
+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) return;
- sd->module->spu_channel_mute_set(sd->video, mute);
+ if (!sd->video_data) return;
+ sd->module->spu_channel_mute_set(sd->video_data, mute);
}
-EAPI Evas_Bool
-emotion_object_spu_mute_get(Evas_Object *obj)
+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 0;
- if (!sd->video) return 0;
- return sd->module->spu_channel_mute_get(sd->video);
+ 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(Evas_Object *obj)
+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) return 0;
- return sd->module->spu_channel_count(sd->video);
+ if (!sd->video_data) return 0;
+ return sd->module->spu_channel_count(sd->video_data);
}
EAPI const char *
-emotion_object_spu_channel_name_get(Evas_Object *obj, int channel)
+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) return NULL;
- return sd->module->spu_channel_name_get(sd->video, channel);
+ if (!sd->video_data) return NULL;
+ return sd->module->spu_channel_name_get(sd->video_data, channel);
}
EAPI void
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+ DBG("channel=%d", channel);
if (!sd->module) return;
- if (!sd->video) return;
- sd->module->spu_channel_set(sd->video, channel);
+ if (!sd->video_data) return;
+ sd->module->spu_channel_set(sd->video_data, channel);
}
EAPI int
-emotion_object_spu_channel_get(Evas_Object *obj)
+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) return 0;
- return sd->module->spu_channel_get(sd->video);
+ if (!sd->video_data) return 0;
+ return sd->module->spu_channel_get(sd->video_data);
}
EAPI int
-emotion_object_chapter_count(Evas_Object *obj)
+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) return 0;
- return sd->module->chapter_count(sd->video);
+ if (!sd->video_data) return 0;
+ return sd->module->chapter_count(sd->video_data);
}
EAPI void
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+ DBG("chapter=%d", chapter);
if (!sd->module) return;
- if (!sd->video) return;
- sd->module->chapter_set(sd->video, chapter);
+ if (!sd->video_data) return;
+ sd->module->chapter_set(sd->video_data, chapter);
}
EAPI int
-emotion_object_chapter_get(Evas_Object *obj)
+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) return 0;
- return sd->module->chapter_get(sd->video);
+ if (!sd->video_data) return 0;
+ return sd->module->chapter_get(sd->video_data);
}
EAPI const char *
-emotion_object_chapter_name_get(Evas_Object *obj, int chapter)
+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) return NULL;
- return sd->module->chapter_name_get(sd->video, chapter);
+ if (!sd->video_data) return NULL;
+ return sd->module->chapter_name_get(sd->video_data, chapter);
}
EAPI void
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+ DBG("speed=%f", speed);
if (!sd->module) return;
- if (!sd->video) return;
- sd->module->speed_set(sd->video, speed);
+ if (!sd->video_data) return;
+ sd->module->speed_set(sd->video_data, speed);
}
EAPI double
-emotion_object_play_speed_get(Evas_Object *obj)
+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) return 0.0;
- return sd->module->speed_get(sd->video);
+ if (!sd->video_data) return 0.0;
+ return sd->module->speed_get(sd->video_data);
}
EAPI void
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
if (!sd->module) return;
- if (!sd->video) return;
- sd->module->eject(sd->video);
+ if (!sd->video_data) return;
+ sd->module->eject(sd->video_data);
}
EAPI const char *
-emotion_object_title_get(Evas_Object *obj)
+emotion_object_title_get(const Evas_Object *obj)
{
Smart_Data *sd;
}
EAPI const char *
-emotion_object_progress_info_get(Evas_Object *obj)
+emotion_object_progress_info_get(const Evas_Object *obj)
{
Smart_Data *sd;
}
EAPI double
-emotion_object_progress_status_get(Evas_Object *obj)
+emotion_object_progress_status_get(const Evas_Object *obj)
{
Smart_Data *sd;
}
EAPI const char *
-emotion_object_ref_file_get(Evas_Object *obj)
+emotion_object_ref_file_get(const Evas_Object *obj)
{
Smart_Data *sd;
}
EAPI int
-emotion_object_ref_num_get(Evas_Object *obj)
+emotion_object_ref_num_get(const Evas_Object *obj)
{
Smart_Data *sd;
}
EAPI int
-emotion_object_spu_button_count_get(Evas_Object *obj)
+emotion_object_spu_button_count_get(const Evas_Object *obj)
{
Smart_Data *sd;
}
EAPI int
-emotion_object_spu_button_get(Evas_Object *obj)
+emotion_object_spu_button_get(const Evas_Object *obj)
{
Smart_Data *sd;
}
EAPI const char *
-emotion_object_meta_info_get(Evas_Object *obj, Emotion_Meta_Info meta)
+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) return NULL;
+ if (!sd->video_data) return NULL;
switch (meta)
{
case EMOTION_META_INFO_TRACK_TITLE:
- return sd->module->meta_get(sd->video, META_TRACK_TITLE);
- break;
+ return sd->module->meta_get(sd->video_data, META_TRACK_TITLE);
case EMOTION_META_INFO_TRACK_ARTIST:
- return sd->module->meta_get(sd->video, META_TRACK_ARTIST);
- break;
+ return sd->module->meta_get(sd->video_data, META_TRACK_ARTIST);
case EMOTION_META_INFO_TRACK_ALBUM:
- return sd->module->meta_get(sd->video, META_TRACK_ALBUM);
- break;
+ return sd->module->meta_get(sd->video_data, META_TRACK_ALBUM);
case EMOTION_META_INFO_TRACK_YEAR:
- return sd->module->meta_get(sd->video, META_TRACK_YEAR);
- break;
+ return sd->module->meta_get(sd->video_data, META_TRACK_YEAR);
case EMOTION_META_INFO_TRACK_GENRE:
- return sd->module->meta_get(sd->video, META_TRACK_GENRE);
- break;
+ return sd->module->meta_get(sd->video_data, META_TRACK_GENRE);
case EMOTION_META_INFO_TRACK_COMMENT:
- return sd->module->meta_get(sd->video, META_TRACK_COMMENT);
- break;
+ 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, META_TRACK_DISCID);
- break;
+ 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(Evas_Object *obj)
+_emotion_video_get(const Evas_Object *obj)
{
Smart_Data *sd;
E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
- return sd->video;
+ 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
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
-// printf("pix get set 1 %p\n", sd->obj);
- evas_object_image_pixels_dirty_set(sd->obj, 1);
- evas_object_smart_callback_call(obj, "frame_decode", NULL);
+
+ if (!sd->anim) sd->anim = ecore_animator_add(_emotion_frame_anim, obj);
}
EAPI void
if (len != sd->len) nlen = 1;
sd->pos = pos;
sd->len = len;
- if (npos) evas_object_smart_callback_call(obj, "position_update", NULL);
- if (nlen) evas_object_smart_callback_call(obj, "length_change", NULL);
+ 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;
- int iw, ih;
+ double tmp;
int changed = 0;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
- evas_object_image_size_get(sd->obj, &iw, &ih);
- if ((w != iw) || (h != ih))
+ if ((w != sd->video.w) || (h != sd->video.h))
{
- if (h > 0) sd->ratio = (double)w / (double)h;
- else sd->ratio = 1.0;
- evas_object_image_size_set(sd->obj, w, h);
+ sd->video.w = w;
+ sd->video.h = h;
+ _emotion_image_data_zero(sd->obj);
changed = 1;
}
- if (ratio != sd->ratio)
+ if (h > 0) tmp = (double)w / (double)h;
+ else tmp = 1.0;
+ if (ratio != tmp) tmp = ratio;
+ if (tmp != sd->ratio)
{
- sd->ratio = ratio;
+ sd->ratio = tmp;
changed = 1;
}
- if (changed) evas_object_smart_callback_call(obj, "frame_resize", NULL);
+ 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
if (sd->play)
{
sd->play = 0;
- evas_object_smart_callback_call(obj, "decode_stop", NULL);
+ 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, "playback_finished", NULL);
+ 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, "audio_level_change", NULL);
+ evas_object_smart_callback_call(obj, SIG_AUDIO_LEVEL_CHANGE, NULL);
}
EAPI void
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
- evas_object_smart_callback_call(obj, "channels_change", NULL);
+ evas_object_smart_callback_call(obj, SIG_CHANNELS_CHANGE, NULL);
}
EAPI void
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
- if (sd->title) free(sd->title);
+ free(sd->title);
sd->title = strdup(title);
- evas_object_smart_callback_call(obj, "title_change", NULL);
+ evas_object_smart_callback_call(obj, SIG_TITLE_CHANGE, NULL);
}
EAPI void
-_emotion_progress_set(Evas_Object *obj, char *info, double stat)
+_emotion_progress_set(Evas_Object *obj, char *info, double st)
{
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
- if (sd->progress.info) free(sd->progress.info);
+ free(sd->progress.info);
sd->progress.info = strdup(info);
- sd->progress.stat = stat;
- evas_object_smart_callback_call(obj, "progress_change", NULL);
+ sd->progress.stat = st;
+ evas_object_smart_callback_call(obj, SIG_PROGRESS_CHANGE, NULL);
}
EAPI void
-_emotion_file_ref_set(Evas_Object *obj, char *file, int num)
+_emotion_file_ref_set(Evas_Object *obj, const char *file, int num)
{
Smart_Data *sd;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
- if (sd->ref.file) free(sd->ref.file);
+ free(sd->ref.file);
sd->ref.file = strdup(file);
sd->ref.num = num;
- evas_object_smart_callback_call(obj, "ref_change", NULL);
+ evas_object_smart_callback_call(obj, SIG_REF_CHANGE, NULL);
}
EAPI void
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
sd->spu.button_num = num;
- evas_object_smart_callback_call(obj, "button_num_change", NULL);
+ evas_object_smart_callback_call(obj, SIG_BUTTON_NUM_CHANGE, NULL);
}
EAPI void
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
sd->spu.button = button;
- evas_object_smart_callback_call(obj, "button_change", NULL);
+ 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, Evas_Object *obj, void *event_info)
+_mouse_move(void *data, Evas *ev __UNUSED__, Evas_Object *obj, void *event_info)
{
Evas_Event_Mouse_Move *e;
Smart_Data *sd;
e = event_info;
sd = data;
if (!sd->module) return;
- if (!sd->video) 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, x, y);
+ sd->module->event_mouse_move_feed(sd->video_data, x, y);
}
static void
-_mouse_down(void *data, Evas *ev, Evas_Object *obj, void *event_info)
+_mouse_down(void *data, Evas *ev __UNUSED__, Evas_Object *obj, void *event_info)
{
Evas_Event_Mouse_Down *e;
Smart_Data *sd;
e = event_info;
sd = data;
if (!sd->module) return;
- if (!sd->video) 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, 1, x, y);
+ sd->module->event_mouse_button_feed(sd->video_data, 1, x, y);
}
static void
obj = data;
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
sd->job = NULL;
+ if (sd->seeking) return;
if (sd->seek)
{
- sd->module->pos_set(sd->video, sd->seek_pos);
+ sd->seeking = 1;
+ sd->module->pos_set(sd->video_data, sd->seek_pos);
sd->seek = 0;
}
}
unsigned char *bgra_data;
sd = data;
- evas_object_image_size_get(obj, &iw, &ih);
- sd->module->video_data_size_get(sd->video, &w, &h);
+ sd->module->video_data_size_get(sd->video_data, &w, &h);
w = (w >> 1) << 1;
h = (h >> 1) << 1;
- if ((w != iw) || (h != ih))
- {
- 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))
+
+ 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))
{
-// printf("pix get set 0 (1)\n");
+ _emotion_image_data_zero(sd->obj);
evas_object_image_pixels_dirty_set(obj, 0);
}
else
{
- format = sd->module->format_get(sd->video);
+ format = sd->module->format_get(sd->video_data);
if ((format == EMOTION_FORMAT_YV12) || (format == EMOTION_FORMAT_I420))
{
unsigned char **rows;
rows = evas_object_image_data_get(obj, 1);
if (rows)
{
- if (sd->module->yuv_rows_get(sd->video, iw, ih,
+ 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);
-// printf("pix get set 0 (2)\n");
evas_object_image_pixels_dirty_set(obj, 0);
}
else if (format == EMOTION_FORMAT_BGRA)
{
- if (sd->module->bgra_data_get(sd->video, &bgra_data))
+ 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);
-// printf("pix get set 0 (3)\n");
evas_object_image_pixels_dirty_set(obj, 0);
}
}
}
-// no need for this because on any new frame decode info from the decoder
-// module, the previous "current frame" is released (done) for us anyway
-// sd->module->frame_done(sd->video);
-
-/*
- evas_object_image_size_get(obj, &iw, &ih);
- sd->module->video_data_size_get(sd->video, &w, &h);
- if ((w != iw) || (h != ih))
- {
- evas_object_image_size_set(obj, w, h);
- iw = w;
- ih = h;
- }
- format = sd->module->format_get(sd->video);
- if ((format == EMOTION_FORMAT_YV12) || (format == EMOTION_FORMAT_I420))
- {
- unsigned char **rows;
- Evas_Pixel_Import_Source ps;
-
- ps.format = EVAS_PIXEL_FORMAT_YUV420P_601;
- ps.w = iw;
- ps.h = ih;
-
- ps.rows = malloc(ps.h * 2 * sizeof(void *));
- if (!ps.rows)
- {
- sd->module->frame_done(sd->video);
- return;
- }
-
- rows = (unsigned char **)ps.rows;
-
- if (sd->module->yuv_rows_get(sd->video, iw, ih,
- rows,
- &rows[ps.h],
- &rows[ps.h + (ps.h / 2)]))
- evas_object_image_pixels_import(obj, &ps);
- evas_object_image_pixels_dirty_set(obj, 0);
- free(ps.rows);
- }
- else if (format == EMOTION_FORMAT_BGRA)
- {
- if (sd->module->bgra_data_get(sd->video, &bgra_data));
- {
- evas_object_image_data_set(obj, bgra_data);
- evas_object_image_pixels_dirty_set(obj, 0);
- }
- }
- sd->module->frame_done(sd->video);
- */
}
/*******************************************/
/* 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;
{
- static const Evas_Smart_Class sc =
+ 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)
{
- E_OBJ_NAME,
- EVAS_SMART_CLASS_VERSION,
- _smart_add,
- _smart_del,
- _smart_move,
- _smart_resize,
- _smart_show,
- _smart_hide,
- _smart_color_set,
- _smart_clip_set,
- _smart_clip_unset,
- NULL
- };
+ 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);
}
}
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)
evas_object_image_data_set(obj, pixel);
}
evas_object_smart_data_set(obj, sd);
+
+ ecore_init();
}
static void
sd = evas_object_smart_data_get(obj);
if (!sd) return;
- if (sd->video) sd->module->file_close(sd->video);
- _emotion_module_close(sd->module, sd->video);
- evas_object_del(sd->obj);
- if (sd->file) free(sd->file);
- if (sd->job) ecore_job_del(sd->job);
- if (sd->progress.info) free(sd->progress.info);
- if (sd->ref.file) free(sd->ref.file);
- free(sd);
-
- ecore_job_shutdown();
+ 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_move(sd->obj, x, y);
+
+ 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
sd = evas_object_smart_data_get(obj);
if (!sd) return;
- evas_object_image_fill_set(sd->obj, 0, 0, w, h);
- evas_object_resize(sd->obj, w, h);
+
+ _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
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
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
sd = evas_object_smart_data_get(obj);
if (!sd) return;
- evas_object_clip_set(sd->obj, clip);
+ 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
sd = evas_object_smart_data_get(obj);
if (!sd) return;
- evas_object_clip_unset(sd->obj);
+ if (sd->crop.clipper)
+ evas_object_clip_unset(sd->crop.clipper);
+ else
+ evas_object_clip_unset(sd->obj);
+ evas_object_clip_unset(sd->bg);
}
+
MAINTAINERCLEANFILES = Makefile.in
-SUBDIRS = xine gstreamer
+SUBDIRS = xine gstreamer generic
--- /dev/null
+#ifndef EMOTION_GENERIC_PLUGIN_H
+#define EMOTION_GENERIC_PLUGIN_H
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <Eina.h>
+
+#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
--- /dev/null
+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
--- /dev/null
+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", <command>);
+
+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;
+
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <Eina.h>
+#include <Evas.h>
+#include <Ecore.h>
+
+#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
+
--- /dev/null
+#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
+
-
MAINTAINERCLEANFILES = Makefile.in
AM_CPPFLAGS = \
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
-@EVAS_CFLAGS@ \
-@ECORE_CFLAGS@ \
-@GST_CFLAGS@
+@EMOTION_CFLAGS@ \
+@EMOTION_CPPFLAGS@ \
+@EFL_EMOTION_BUILD@ \
+@GSTREAMER_CFLAGS@ \
+@GSTREAMER_INTERFACE_CFLAGS@ \
+@ECORE_X_CFLAGS@
-if BUILD_GSTREAMER_MODULE
+if EMOTION_BUILD_GSTREAMER
+if !EMOTION_STATIC_BUILD_GSTREAMER
pkgdir = $(libdir)/emotion
pkg_LTLIBRARIES = gstreamer.la
gstreamer_la_SOURCES = \
emotion_gstreamer.c \
-emotion_gstreamer.h \
-emotion_gstreamer_pipeline.c \
-emotion_gstreamer_pipeline.h \
-emotion_gstreamer_pipeline_cdda.c \
-emotion_gstreamer_pipeline_dvd.c \
-emotion_gstreamer_pipeline_file.c \
-emotion_gstreamer_pipeline_uri.c
-gstreamer_la_LIBADD = @EVAS_LIBS@ @ECORE_LIBS@ @GST_LIBS@ $(top_builddir)/src/lib/libemotion.la
-gstreamer_la_LDFLAGS = -module -avoid-version
+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
\ No newline at end of file
+endif
+endif
+
+EXTRA_DIST = emotion_gstreamer.h
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Evas.h>
+#include <Ecore.h>
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideosink.h>
+
+#ifdef HAVE_ECORE_X
+# include <Ecore_X.h>
+# include <Ecore_Evas.h>
+# ifdef HAVE_XOVERLAY_H
+# include <gst/interfaces/xoverlay.h>
+# 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);
+}
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Evas.h>
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideosink.h>
+
+#ifdef HAVE_ECORE_X
+# include <Ecore_X.h>
+# include <Ecore_Evas.h>
+# ifdef HAVE_XOVERLAY_H
+# include <gst/interfaces/xoverlay.h>
+# 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 }
+};
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Evas.h>
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideosink.h>
+
+#ifdef HAVE_ECORE_X
+# include <Ecore_X.h>
+# include <Ecore_Evas.h>
+# ifdef HAVE_XOVERLAY_H
+# include <gst/interfaces/xoverlay.h>
+# 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__)
+{
+}
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-#include <unistd.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
#include <fcntl.h>
+#include <Eina.h>
+#include <Evas.h>
+#include <Ecore.h>
+
+#define HTTP_STREAM 0
+#define RTSP_STREAM 1
+#include <glib.h>
+#include <gst/gst.h>
+#include <glib-object.h>
+#include <gst/video/gstvideosink.h>
+#include <gst/video/video.h>
+
+#ifdef HAVE_ECORE_X
+# include <Ecore_X.h>
+# include <Ecore_Evas.h>
+# ifdef HAVE_XOVERLAY_H
+# include <gst/interfaces/xoverlay.h>
+# endif
+#endif
+
#include "Emotion.h"
#include "emotion_private.h"
#include "emotion_gstreamer.h"
-#include "emotion_gstreamer_pipeline.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 int _eos_timer_fct (void *data);
-static int _em_fd_ev_active (void *data, Ecore_Fd_Handler *fdh);
static void _for_each_tag (GstTagList const* list, gchar const* tag, void *data);
static void _free_metadata (Emotion_Gstreamer_Metadata *m);
static unsigned char em_init (Evas_Object *obj,
void **emotion_video,
- Emotion_Module_Options *opt);
-
-static int em_shutdown (void *video);
+ Emotion_Module_Options *opt);
static unsigned char em_file_open (const char *file,
Evas_Object *obj,
static void em_pos_set (void *video,
double pos);
-static void em_vis_set (void *video,
- Emotion_Vis vis);
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_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 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_stop, /* stop */
em_size_get, /* size_get */
em_pos_set, /* pos_set */
- em_vis_set, /* vis_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_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)
+em_init(Evas_Object *obj,
+ void **emotion_video,
+ Emotion_Module_Options *opt __UNUSED__)
{
Emotion_Gstreamer_Video *ev;
GError *error;
- int fds[2];
if (!emotion_video)
return 0;
if (!ev) return 0;
ev->obj = obj;
- ev->obj_data = NULL;
/* Initialization of gstreamer */
if (!gst_init_check(NULL, NULL, &error))
- goto failure_gstreamer;
-
- /* We allocate the sinks lists */
- ev->video_sinks = ecore_list_new();
- if (!ev->video_sinks)
- goto failure_video_sinks;
- ecore_list_free_cb_set(ev->video_sinks, ECORE_FREE_CB(free));
- ev->audio_sinks = ecore_list_new();
- if (!ev->audio_sinks)
- goto failure_audio_sinks;
- ecore_list_free_cb_set(ev->audio_sinks, ECORE_FREE_CB(free));
-
- *emotion_video = ev;
+ goto failure;
/* Default values */
ev->ratio = 1.0;
- ev->video_sink_nbr = 0;
- ev->audio_sink_nbr = 0;
- ev->vis = EMOTION_VIS_GOOM;
+ ev->vis = EMOTION_VIS_NONE;
+ ev->volume = 0.8;
+ ev->play_started = 0;
+ ev->delete_me = EINA_FALSE;
+ ev->threads = NULL;
- /* Create the file descriptors */
- 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);
- }
- else
- goto failure_pipe;
+ *emotion_video = ev;
return 1;
-failure_pipe:
- ecore_list_destroy(ev->audio_sinks);
-failure_audio_sinks:
- ecore_list_destroy(ev->video_sinks);
-failure_video_sinks:
-failure_gstreamer:
+failure:
free(ev);
return 0;
}
-static int
+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;
if (!ev)
return 0;
- ecore_main_fd_handler_del(ev->fd_ev_handler);
+ if (ev->threads)
+ {
+ Ecore_Thread *t;
- close(ev->fd_ev_write);
- close(ev->fd_ev_read);
+ EINA_LIST_FREE(ev->threads, t)
+ ecore_thread_cancel(t);
- /* FIXME: and the evas object ? */
- if (ev->obj_data) free(ev->obj_data);
+ ev->delete_me = EINA_TRUE;
+ return EINA_FALSE;
+ }
+
+ if (ev->in != ev->out)
+ {
+ ev->delete_me = EINA_TRUE;
+ return EINA_FALSE;
+ }
- ecore_list_destroy(ev->video_sinks);
- ecore_list_destroy(ev->audio_sinks);
+ em_cleanup(ev);
free(ev);
static unsigned char
em_file_open(const char *file,
- Evas_Object *obj,
- void *video)
+ Evas_Object *obj,
+ void *video)
{
Emotion_Gstreamer_Video *ev;
+ Eina_Strbuf *sbuf = NULL;
+ const char *uri;
ev = (Emotion_Gstreamer_Video *)video;
- ev->pipeline = gst_pipeline_new("pipeline");
+ 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 0;
+ return EINA_FALSE;
ev->eos_bus = gst_pipeline_get_bus(GST_PIPELINE(ev->pipeline));
if (!ev->eos_bus)
{
- gst_object_unref(ev->pipeline);
- return 0;
+ 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;
- /* CD Audio */
- if (strstr(file, "cdda://"))
- {
- const char *device = NULL;
- unsigned int track = 1;
-
- device = file + strlen("cdda://");
- if (device[0] == '/')
- {
- char *tmp;
-
- if ((tmp = strchr(device, '?')) || (tmp = strchr(device, '#')))
- {
- sscanf(tmp + 1, "%d", &track);
- tmp[0] = '\0';
- }
- }
- else
- {
- device = NULL;
- sscanf(file, "cdda://%d", &track);
- }
- fprintf(stderr, "[Emotion] [gst] build CD Audio pipeline\n");
- if (!(emotion_pipeline_cdda_build(ev, device, track)))
- {
- fprintf(stderr, "[Emotion] [gst] error while building CD Audio pipeline\n");
- gst_object_unref(ev->pipeline);
- return 0;
- }
- }
- /* Dvd */
- else if (strstr(file, "dvd://"))
- {
-
- fprintf(stderr, "[Emotion] [gst] build DVD pipeline\n");
- if (!(emotion_pipeline_dvd_build(ev, NULL)))
- {
- fprintf(stderr, "[Emotion] [gst] error while building DVD pipeline\n");
- gst_object_unref(ev->pipeline);
- return 0;
- }
- }
- /* http */
- else if (strstr(file, "http://"))
- {
- fprintf(stderr, "[Emotion] [gst] build URI pipeline\n");
- if (!(emotion_pipeline_uri_build(ev, file)))
- {
- fprintf(stderr, "[Emotion] [gst] error while building URI pipeline\n");
- gst_object_unref(ev->pipeline);
- return 0;
- }
- }
- /* Normal media file */
- else
- {
- const char *filename;
-
- filename = strstr(file, "file://")
- ? file + strlen("file://")
- : file;
-
- fprintf(stderr, "[Emotion] [gst] build file pipeline\n");
- if (!(emotion_pipeline_file_build(ev, filename)))
- {
- fprintf(stderr, "[Emotion] [gst] error while building File pipeline\n");
- gst_object_unref(ev->pipeline);
- return 0;
- }
- }
-
ev->position = 0.0;
- {
- /* on recapitule : */
- Emotion_Video_Sink *vsink;
- Emotion_Audio_Sink *asink;
-
- vsink = (Emotion_Video_Sink *)ecore_list_first_goto(ev->video_sinks);
- if (vsink)
- {
- fprintf(stderr, "video : \n");
- fprintf(stderr, " size : %dx%d\n", vsink->width, vsink->height);
- fprintf(stderr, " fps : %d/%d\n", vsink->fps_num, vsink->fps_den);
- fprintf(stderr, " fourcc : %" GST_FOURCC_FORMAT "\n", GST_FOURCC_ARGS(vsink->fourcc));
- fprintf(stderr, " length : %" GST_TIME_FORMAT "\n\n",
- GST_TIME_ARGS((guint64)(vsink->length_time * GST_SECOND)));
- }
-
- asink = (Emotion_Audio_Sink *)ecore_list_first_goto(ev->audio_sinks);
- if (asink)
- {
- fprintf(stderr, "audio : \n");
- fprintf(stderr, " chan : %d\n", asink->channels);
- fprintf(stderr, " rate : %d\n", asink->samplerate);
- fprintf(stderr, " length : %" GST_TIME_FORMAT "\n\n",
- GST_TIME_ARGS((guint64)(asink->length_time * GST_SECOND)));
- }
- }
-
- if (ev->metadata)
- _free_metadata(ev->metadata);
- ev->metadata = calloc(1, sizeof(Emotion_Gstreamer_Metadata));
-
- _eos_timer_fct(ev);
-
return 1;
}
if (!ev)
return;
- /* we clear the sink lists */
- ecore_list_clear(ev->video_sinks);
- ecore_list_clear(ev->audio_sinks);
-
- /* shutdown eos */
- if (ev->eos_timer)
+ if (ev->threads)
{
- ecore_timer_del(ev->eos_timer);
- ev->eos_timer = NULL;
- }
+ Ecore_Thread *t;
- if (ev->eos_bus)
- {
- gst_object_unref(GST_OBJECT(ev->eos_bus));
- ev->eos_bus = NULL;
+ EINA_LIST_FREE(ev->threads, t)
+ ecore_thread_cancel(t);
}
- if (ev->metadata)
- {
- _free_metadata(ev->metadata);
- ev->metadata = NULL;
- }
+ em_cleanup(ev);
- if (ev->pipeline)
- {
- gst_element_set_state(ev->pipeline, GST_STATE_NULL);
- gst_object_unref(ev->pipeline);
- ev->pipeline = NULL;
- }
+ ev->pipeline_parsed = EINA_FALSE;
+ ev->play_started = 0;
}
static void
em_play(void *video,
- double pos)
+ double pos __UNUSED__)
{
Emotion_Gstreamer_Video *ev;
ev = (Emotion_Gstreamer_Video *)video;
- gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);
- ev->play = 1;
+ if (!ev->pipeline) return ;
- /* eos */
- ev->eos_timer = ecore_timer_add(0.1, _eos_timer_fct, ev);
+ if (ev->pipeline_parsed)
+ gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);
+ ev->play = 1;
+ ev->play_started = 1;
}
static void
ev = (Emotion_Gstreamer_Video *)video;
- /* shutdown eos */
- if (ev->eos_timer)
- {
- ecore_timer_del(ev->eos_timer);
- ev->eos_timer = NULL;
- }
+ if (!ev->pipeline) return ;
- gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
+ 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)
+ int *width,
+ int *height)
{
Emotion_Gstreamer_Video *ev;
- Emotion_Video_Sink *vsink;
+ Emotion_Video_Stream *vstream;
ev = (Emotion_Gstreamer_Video *)video;
- vsink = (Emotion_Video_Sink *)ecore_list_index_goto(ev->video_sinks, ev->video_sink_nbr);
- if (vsink)
- {
- if (width) *width = vsink->width;
- if (height) *height = vsink->height;
- }
- else
+ 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 = 0;
- if (height) *height = 0;
+ 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)
+ double pos)
{
Emotion_Gstreamer_Video *ev;
- Emotion_Video_Sink *vsink;
- Emotion_Audio_Sink *asink;
ev = (Emotion_Gstreamer_Video *)video;
- if (ev->seek_to_pos == pos) return;
+ if (!ev->pipeline) return ;
- vsink = (Emotion_Video_Sink *)ecore_list_index_goto(ev->video_sinks, ev->video_sink_nbr);
- asink = (Emotion_Audio_Sink *)ecore_list_index_goto(ev->video_sinks, ev->audio_sink_nbr);
+ if (ev->play)
+ gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
- if (vsink)
- {
- gst_element_seek(vsink->sink, 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 (asink)
- {
- gst_element_seek(asink->sink, 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);
- }
- ev->seek_to_pos = pos;
+ 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 void
-em_vis_set(void *video,
- Emotion_Vis vis)
+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 = (Emotion_Gstreamer_Video *)video;
+ ev = video;
+ fmt = GST_FORMAT_TIME;
- if (ev->vis == vis) return;
- ev->vis = vis;
+ 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_len_get(void *video)
+em_buffer_size_get(void *video)
{
Emotion_Gstreamer_Video *ev;
- Emotion_Video_Sink *vsink;
- ev = (Emotion_Gstreamer_Video *)video;
+ GstQuery *query;
+ gboolean busy;
+ gint percent;
- vsink = (Emotion_Video_Sink *)ecore_list_index_goto(ev->video_sinks, ev->video_sink_nbr);
- if (vsink)
- return (double)vsink->length_time;
+ ev = video;
- return 0.0;
+ 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_Sink *vsink;
+ Emotion_Video_Stream *vstream;
ev = (Emotion_Gstreamer_Video *)video;
- vsink = (Emotion_Video_Sink *)ecore_list_index_goto(ev->video_sinks, ev->video_sink_nbr);
- if (vsink)
- return vsink->fps_num;
+ 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;
}
em_fps_den_get(void *video)
{
Emotion_Gstreamer_Video *ev;
- Emotion_Video_Sink *vsink;
+ Emotion_Video_Stream *vstream;
ev = (Emotion_Gstreamer_Video *)video;
- vsink = (Emotion_Video_Sink *)ecore_list_index_goto(ev->video_sinks, ev->video_sink_nbr);
- if (vsink)
- return vsink->fps_den;
+ 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;
}
em_fps_get(void *video)
{
Emotion_Gstreamer_Video *ev;
- Emotion_Video_Sink *vsink;
+ Emotion_Video_Stream *vstream;
ev = (Emotion_Gstreamer_Video *)video;
- vsink = (Emotion_Video_Sink *)ecore_list_index_goto(ev->video_sinks, ev->video_sink_nbr);
- if (vsink)
- return (double)vsink->fps_num / (double)vsink->fps_den;
+ 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;
}
em_pos_get(void *video)
{
Emotion_Gstreamer_Video *ev;
+ GstFormat fmt;
+ gint64 val;
+ gboolean ret;
- ev = (Emotion_Gstreamer_Video *)video;
+ 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)
{
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)
{
ev = (Emotion_Gstreamer_Video *)video;
- if (ecore_list_empty_is(ev->video_sinks))
+ _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
+ if (!eina_list_count(ev->video_streams))
return 0;
return 1;
ev = (Emotion_Gstreamer_Video *)video;
- if (ecore_list_empty_is(ev->audio_sinks))
+ _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)
+em_seekable(void *video __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return 1;
}
static void
-em_frame_done(void *video)
+em_frame_done(void *video __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
}
static Emotion_Format
em_format_get(void *video)
{
Emotion_Gstreamer_Video *ev;
- Emotion_Video_Sink *vsink;
+ Emotion_Video_Stream *vstream;
ev = (Emotion_Gstreamer_Video *)video;
- vsink = (Emotion_Video_Sink *)ecore_list_index_goto(ev->video_sinks, ev->video_sink_nbr);
- if (vsink)
+ 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 (vsink->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;
- }
+ 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;
}
em_video_data_size_get(void *video, int *w, int *h)
{
Emotion_Gstreamer_Video *ev;
- Emotion_Video_Sink *vsink;
+ Emotion_Video_Stream *vstream;
ev = (Emotion_Gstreamer_Video *)video;
- vsink = (Emotion_Video_Sink *)ecore_list_index_goto(ev->video_sinks, ev->video_sink_nbr);
- if (vsink)
- {
- *w = vsink->width;
- *h = vsink->height;
- }
- else
+ 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 = 0;
- *h = 0;
+ *w = vstream->width;
+ *h = vstream->height;
+
+ return ;
}
+
+ on_error:
+ *w = 0;
+ *h = 0;
}
static int
-em_yuv_rows_get(void *video,
- int w,
- int h,
- unsigned char **yrows,
- unsigned char **urows,
- unsigned char **vrows)
+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__)
{
- Emotion_Gstreamer_Video *ev;
- int i;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
- if (ev->obj_data)
- {
- if (em_format_get(video) == EMOTION_FORMAT_I420)
- {
- for (i = 0; i < h; i++)
- yrows[i] = &ev->obj_data[i * w];
-
- for (i = 0; i < (h / 2); i++)
- urows[i] = &ev->obj_data[h * w + i * (w / 2)];
-
- for (i = 0; i < (h / 2); i++)
- vrows[i] = &ev->obj_data[h * w + h * (w /4) + i * (w / 2)];
- }
- else if (em_format_get(video) == EMOTION_FORMAT_YV12)
- {
- for (i = 0; i < h; i++)
- yrows[i] = &ev->obj_data[i * w];
-
- for (i = 0; i < (h / 2); i++)
- vrows[i] = &ev->obj_data[h * w + i * (w / 2)];
-
- for (i = 0; i < (h / 2); i++)
- urows[i] = &ev->obj_data[h * w + h * (w /4) + i * (w / 2)];
- }
- else
- return 0;
-
- return 1;
- }
-
return 0;
}
static int
-em_bgra_data_get(void *video, unsigned char **bgra_data)
+em_bgra_data_get(void *video __UNUSED__, unsigned char **bgra_data __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
- if (ev->obj_data && em_format_get(video) == EMOTION_FORMAT_BGRA)
- {
- *bgra_data = ev->obj_data;
- return 1;
- }
return 0;
}
static void
-em_event_feed(void *video, int event)
+em_event_feed(void *video __UNUSED__, int event __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
}
static void
-em_event_mouse_button_feed(void *video, int button, int x, int y)
+em_event_mouse_button_feed(void *video __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
}
static void
-em_event_mouse_move_feed(void *video, int x, int y)
+em_event_mouse_move_feed(void *video __UNUSED__, int x __UNUSED__, int y __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
}
/* Video channels */
ev = (Emotion_Gstreamer_Video *)video;
- return ecore_list_count(ev->video_sinks);
+ _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
+ return eina_list_count(ev->video_streams);
}
static void
-em_video_channel_set(void *video,
- int channel)
+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... */
}
ev = (Emotion_Gstreamer_Video *)video;
- return ev->video_sink_nbr;
+ _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
+ return ev->video_stream_nbr;
}
static const char *
-em_video_channel_name_get(void *video,
- int channel)
+em_video_channel_name_get(void *video __UNUSED__,
+ int channel __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return NULL;
}
static void
em_video_channel_mute_set(void *video,
- int mute)
+ int mute)
{
Emotion_Gstreamer_Video *ev;
ev = (Emotion_Gstreamer_Video *)video;
- return ecore_list_count(ev->audio_sinks);
+ _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
+ return eina_list_count(ev->audio_streams);
}
static void
-em_audio_channel_set(void *video,
- int channel)
+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... */
}
ev = (Emotion_Gstreamer_Video *)video;
- return ev->audio_sink_nbr;
+ _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
+ return ev->audio_stream_nbr;
}
static const char *
-em_audio_channel_name_get(void *video,
- int channel)
+em_audio_channel_name_get(void *video __UNUSED__,
+ int channel __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return NULL;
}
+#define GST_PLAY_FLAG_AUDIO (1 << 1)
+
static void
em_audio_channel_mute_set(void *video,
- int mute)
+ 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;
- GstElement *volume;
ev = (Emotion_Gstreamer_Video *)video;
- if (ev->audio_mute == mute)
- return;
+ if (!ev->pipeline) return ;
ev->audio_mute = mute;
- volume = gst_bin_get_by_name(GST_BIN(ev->pipeline), "volume");
- if (!volume) return;
-
- if (mute)
- g_object_set(G_OBJECT(volume), "volume", 0.0, NULL);
- else
- g_object_set(G_OBJECT(volume), "volume", ev->volume * 10.0, NULL);
- gst_object_unref(volume);
+ g_object_set(G_OBJECT(ev->pipeline), "mute", !!mute, NULL);
}
static int
static void
em_audio_channel_volume_set(void *video,
- double vol)
+ double vol)
{
Emotion_Gstreamer_Video *ev;
- GstElement *volume;
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;
- volume = gst_bin_get_by_name(GST_BIN(ev->pipeline), "volume");
- if (!volume) return;
- g_object_set(G_OBJECT(volume), "volume",
- vol * 10.0, NULL);
- gst_object_unref(volume);
+ g_object_set(G_OBJECT(ev->pipeline), "volume", vol, NULL);
}
static double
/* spu stuff */
static int
-em_spu_channel_count(void *video)
+em_spu_channel_count(void *video __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return 0;
}
static void
-em_spu_channel_set(void *video, int channel)
+em_spu_channel_set(void *video __UNUSED__, int channel __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
}
static int
-em_spu_channel_get(void *video)
+em_spu_channel_get(void *video __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return 1;
}
static const char *
-em_spu_channel_name_get(void *video, int channel)
+em_spu_channel_name_get(void *video __UNUSED__, int channel __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
return NULL;
}
static void
-em_spu_channel_mute_set(void *video, int mute)
+em_spu_channel_mute_set(void *video __UNUSED__, int mute __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
}
static int
-em_spu_channel_mute_get(void *video)
+em_spu_channel_mute_get(void *video __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return 0;
}
static int
-em_chapter_count(void *video)
+em_chapter_count(void *video __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
return 0;
}
static void
-em_chapter_set(void *video, int chapter)
+em_chapter_set(void *video __UNUSED__, int chapter __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
}
static int
-em_chapter_get(void *video)
+em_chapter_get(void *video __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return 0;
}
static const char *
-em_chapter_name_get(void *video, int chapter)
+em_chapter_name_get(void *video __UNUSED__, int chapter __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return NULL;
}
static void
-em_speed_set(void *video, double speed)
+em_speed_set(void *video __UNUSED__, double speed __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
}
static double
-em_speed_get(void *video)
+em_speed_get(void *video __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return 1.0;
}
static int
-em_eject(void *video)
+em_eject(void *video __UNUSED__)
{
- Emotion_Gstreamer_Video *ev;
-
- ev = (Emotion_Gstreamer_Video *)video;
-
return 1;
}
em_meta_get(void *video, int meta)
{
Emotion_Gstreamer_Video *ev;
- const char *str;
+ const char *str = NULL;
ev = (Emotion_Gstreamer_Video *)video;
switch (meta)
{
case META_TRACK_TITLE:
- str = ev->metadata->title;
- break;
+ str = ev->metadata->title;
+ break;
case META_TRACK_ARTIST:
- str = ev->metadata->artist;
- break;
+ str = ev->metadata->artist;
+ break;
case META_TRACK_ALBUM:
- str = ev->metadata->album;
- break;
+ str = ev->metadata->album;
+ break;
case META_TRACK_YEAR:
- str = ev->metadata->year;
- break;
+ str = ev->metadata->year;
+ break;
case META_TRACK_GENRE:
- str = ev->metadata->genre;
- break;
+ str = ev->metadata->genre;
+ break;
case META_TRACK_COMMENT:
- str = ev->metadata->comment;
- break;
+ str = ev->metadata->comment;
+ break;
case META_TRACK_DISCID:
- str = ev->metadata->disc_id;
- break;
+ str = ev->metadata->disc_id;
+ break;
default:
- break;
+ break;
}
return str;
}
-unsigned char
+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,
- Emotion_Video_Module **module,
- void **video,
- Emotion_Module_Options *opt)
+ 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 0;
+ 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 0;
+ 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 1;
+ return EINA_TRUE;
}
-void
-module_close(Emotion_Video_Module *module,
- void *video)
+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)
+ gchar const* tag,
+ void *data)
{
Emotion_Gstreamer_Video *ev;
- const GValue *val;
int i;
int count;
if (!ev || !ev->metadata) return;
count = gst_tag_list_get_tag_size(list, tag);
- val = gst_tag_list_get_value_index(list, tag, 0);
for (i = 0; i < count; i++)
{
- if (!strcmp(tag, GST_TAG_TITLE))
- {
- char *str;
- if (ev->metadata->title) 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;
- if (ev->metadata->album) 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;
- if (ev->metadata->artist) 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;
- if (ev->metadata->genre) 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;
- if (ev->metadata->comment) 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;
- if (ev->metadata->year) g_free(ev->metadata->year);
- date = gst_tag_list_get_value_index(list, GST_TAG_DATE, 0);
- if (date)
+ 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;
- if (ev->metadata->count) 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;
- }
+ 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;
- if (ev->metadata->disc_id) 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;
- }
+ 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
}
{
if (!m) return;
- if (m->title) g_free(m->title);
- if (m->album) g_free(m->album);
- if (m->artist) g_free(m->artist);
- if (m->genre) g_free(m->genre);
- if (m->comment) g_free(m->comment);
- if (m->year) g_free(m->year);
- if (m->count) g_free(m->count);
- if (m->disc_id) g_free(m->disc_id);
+ 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 int
-_em_fd_ev_active(void *data, Ecore_Fd_Handler *fdh)
+static Eina_Bool
+_em_restart_stream(void *data)
{
- int fd;
- int len;
- void *buf[2];
- unsigned char *frame_data;
Emotion_Gstreamer_Video *ev;
- GstBuffer *buffer;
ev = data;
- fd = ecore_main_fd_handler_fd_get(fdh);
- while ((len = read(fd, buf, sizeof(buf))) > 0)
+ ev->pipeline = gstreamer_video_sink_new(ev, ev->obj, ev->uri);
+
+ if (ev->pipeline)
{
- if (len == sizeof(buf))
- {
- Emotion_Video_Sink *vsink;
-
- frame_data = buf[0];
- buffer = buf[1];
- _emotion_frame_new(ev->obj);
- vsink = (Emotion_Video_Sink *)ecore_list_index_goto(ev->video_sinks, ev->video_sink_nbr);
- if (vsink) _emotion_video_pos_update(ev->obj, ev->position, vsink->length_time);
- }
+ 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);
}
- return 1;
+
+ restart_idler = NULL;
+
+ return ECORE_CALLBACK_CANCEL;
}
-static int
-_eos_timer_fct(void *data)
+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
+_main_frame_resize(void *data)
+{
+ Emotion_Gstreamer_Video *ev = data;
+ double ratio;
+
+ ratio = (double)ev->src_width / (double)ev->src_height;
+ _emotion_frame_resize(ev->obj, ev->src_width, ev->src_height, ratio);
+}
+
+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))
+ {
+ ecore_main_loop_thread_safe_call_async(_main_frame_resize, ev);
+ 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;
- ev = (Emotion_Gstreamer_Video *)data;
- while ((msg = gst_bus_poll(ev->eos_bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_TAG, 0)))
+ send = data;
+ ev = send->ev;
+ msg = send->msg;
+
+ if (ev->play_started && !ev->delete_me)
{
- switch (GST_MESSAGE_TYPE(msg))
- {
- case GST_MESSAGE_ERROR:
- {
- gchar *debug;
- GError *err;
-
- gst_message_parse_error(msg, &err, &debug);
- g_free(debug);
-
- g_print("Error: %s\n", err->message);
- g_error_free(err);
-
- break;
- }
- case GST_MESSAGE_EOS:
- if (ev->eos_timer)
- {
- ecore_timer_del(ev->eos_timer);
- ev->eos_timer = NULL;
- }
- ev->play = 0;
- _emotion_decode_stop(ev->obj);
- _emotion_playback_finished(ev->obj);
- break;
- case GST_MESSAGE_TAG:
- {
- 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;
- }
- default:
- break;
- }
- gst_message_unref(msg);
+ _emotion_playback_started(ev->obj);
+ ev->play_started = 0;
}
- return 1;
+
+ 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;
}
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
#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);
-#include <Evas.h>
-#include <Ecore.h>
-#include <Ecore_Data.h>
-
-#define HTTP_STREAM 0
-#define RTSP_STREAM 1
-#include <gst/gst.h>
-
-#include "emotion_private.h"
-
-
-typedef struct _Emotion_Video_Sink Emotion_Video_Sink;
+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_Sink
+struct _Emotion_Video_Stream
{
- GstElement *sink;
gdouble length_time;
gint width;
gint height;
gint fps_num;
gint fps_den;
guint32 fourcc;
+ int index;
};
-typedef struct _Emotion_Audio_Sink Emotion_Audio_Sink;
-
-struct _Emotion_Audio_Sink
+struct _Emotion_Audio_Stream
{
- GstElement *sink;
gdouble length_time;
gint channels;
gint samplerate;
};
-typedef struct _Emotion_Gstreamer_Metadata Emotion_Gstreamer_Metadata;
-
struct _Emotion_Gstreamer_Metadata
{
char *title;
char *disc_id;
};
-
-typedef struct _Emotion_Gstreamer_Video Emotion_Gstreamer_Video;
-
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;
- Ecore_Timer *eos_timer;
- /* Sinks */
- Ecore_List *video_sinks;
- Ecore_List *audio_sinks;
+ /* Strams */
+ Eina_List *video_streams;
+ Eina_List *audio_streams;
- int video_sink_nbr;
- int audio_sink_nbr;
+ 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;
- unsigned char *obj_data;
/* Characteristics of stream */
double position;
volatile int seek_to;
volatile int get_poslen;
- volatile double seek_to_pos;
-
- int fd_ev_read;
- int fd_ev_write;
- Ecore_Fd_Handler *fd_ev_handler;
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;
- unsigned char play : 1;
- unsigned char video_mute : 1;
- unsigned char audio_mute : 1;
+ 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 */
};
-unsigned char module_open(Evas_Object *obj,
- Emotion_Video_Module **module,
- void **video, Emotion_Module_Options *opt);
+struct _Emotion_Gstreamer_Buffer
+{
+ Emotion_Gstreamer_Video *ev;
+ EvasVideoSinkPrivate *sink;
+
+ GstBuffer *frame;
-void module_close(Emotion_Video_Module *module,
- void *video);
+ 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__ */
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Evas.h>
+#include <Ecore.h>
+
+#define HTTP_STREAM 0
+#define RTSP_STREAM 1
+#include <glib.h>
+#include <gst/gst.h>
+#include <glib-object.h>
+#include <gst/video/gstvideosink.h>
+#include <gst/video/video.h>
+
+#ifdef HAVE_ECORE_X
+# include <Ecore_X.h>
+# include <Ecore_Evas.h>
+# ifdef HAVE_XOVERLAY_H
+# include <gst/interfaces/xoverlay.h>
+# 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 <vtorri@univ-evry.fr>");
+}
+
+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);
+ fprintf(stderr, "resize: %i, %i\n", w, h);
+#endif
+}
+
+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;
+ EvasVideoSinkPrivate *priv = NULL;
+
+ if (!ev->send) return ;
+
+ send = ev->send;
+ priv = send->sink;
+ send->force = EINA_TRUE;
+ ev->send = NULL;
+
+ if (priv->samsung)
+ evas_video_sink_samsung_main_render(send);
+ else
+ 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;
+
+ GstElementFactory *cfactory = NULL;
+ GstElement *convert = NULL, *filter = NULL, *queue = NULL;
+ GstPad *pad = NULL, *teepad = NULL;
+ GstCaps *caps = NULL;
+ Eina_List *l, *engines;
+ const char *ename, *engine = NULL;
+
+ 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->stream && !ev->convert)
+ {
+ cfactory = gst_element_factory_find("fimcconvert");
+ if (!cfactory) return;
+
+ convert = gst_element_factory_create(cfactory, NULL);
+ if (!convert) return;
+
+ // add capsfilter to limit size and formats based on the backend
+ filter = gst_element_factory_make("capsfilter", "fimccapsfilter");
+ if (!filter)
+ {
+ gst_object_unref(convert);
+ return;
+ }
+
+ 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 (strstr(engine, "software") != NULL)
+ {
+ caps = gst_caps_new_simple("video/x-raw-rgb",
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ NULL);
+ }
+ else if (strstr(engine, "gl") != NULL)
+ {
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ NULL);
+ }
+ g_object_set(G_OBJECT(filter), "caps", caps, NULL);
+ gst_caps_unref(caps);
+
+ // add new elements to the pipeline
+ 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_many(GST_BIN(ev->sink), convert, filter, NULL);
+ gst_element_link_many(ev->tee, convert, filter, 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);
+
+ gst_element_sync_state_with_parent(convert);
+ gst_element_sync_state_with_parent(filter);
+
+ ev->eteepad = teepad;
+ ev->convert = convert;
+ evas_render_method_list_free(engines);
+
+ INF("add fimcconvert element. video size: %dx%d. emotion object size: %dx%d",
+ ev->src_width, ev->src_height, width, height);
+ }
+ // set size again to the capsfilter when the image is resized
+ else if (ev->convert)
+ {
+ filter = gst_bin_get_by_name(GST_BIN(ev->sink), "fimccapsfilter");
+
+ 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 (strstr(engine, "software") != NULL)
+ {
+ caps = gst_caps_new_simple("video/x-raw-rgb",
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ NULL);
+ }
+ else if (strstr(engine, "gl") != NULL)
+ {
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ NULL);
+ }
+
+ g_object_set(G_OBJECT(filter), "caps", caps, NULL);
+ gst_caps_unref(caps);
+ evas_render_method_list_free(engines);
+
+ INF("set capsfilter size again:. video size: %dx%d. emotion object size: %dx%d",
+ ev->src_width, ev->src_height, width, height);
+ }
+}
+
+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;
+}
-
MAINTAINERCLEANFILES = Makefile.in
AM_CPPFLAGS = \
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
-@EVAS_CFLAGS@ \
-@ECORE_CFLAGS@ \
+@EMOTION_CFLAGS@ \
+@EMOTION_CPPFLAGS@ \
+@EFL_EMOTION_BUILD@ \
@XINE_CFLAGS@
-if BUILD_XINE_MODULE
+if EMOTION_BUILD_XINE
+if !EMOTION_STATIC_BUILD_XINE
pkgdir = $(libdir)/emotion
pkg_LTLIBRARIES = xine.la
-xine_la_SOURCES = \
+xine_la_SOURCES = \
emotion_xine.c \
emotion_xine.h \
emotion_xine_vo_out.c
-xine_la_LIBADD = @EVAS_LIBS@ @ECORE_LIBS@ @XINE_LIBS@ $(top_builddir)/src/lib/libemotion.la -lpthread
-xine_la_LDFLAGS = -module -avoid-version
+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
-xine_la_DEPENDENCIES = $(top_builddir)/config.h
endif
+endif
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Evas.h>
+#include <Ecore.h>
+
#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 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 void em_vis_set (void *ef, Emotion_Vis vis);
+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);
/* internal util calls */
static void *_em_slave (void *par);
static void _em_slave_event (void *data, int type, void *arg);
-static int _em_fd_active (void *data, Ecore_Fd_Handler *fdh);
+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 int _em_fd_ev_active (void *data, Ecore_Fd_Handler *fdh);
+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);
xine_config_update_entry(ev->decoder, &cf);
}
}
- printf("OPEN VIDEO PLUGIN...\n");
+ DBG("OPEN VIDEO PLUGIN...");
if (!ev->opt_no_video)
ev->video = xine_open_video_driver(ev->decoder, "emotion",
XINE_VISUAL_TYPE_NONE, ev);
- printf("RESULT: xine_open_video_driver() = %p\n", ev->video);
+ 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);
case 3: /* shutdown */
{
_em_module_event(ev, 3);
- printf("EX shutdown stop\n");
+ DBG("shutdown stop");
xine_stop(ev->stream);
// pthread_mutex_lock(&(ev->get_pos_len_mutex));
if (!ev->get_pos_thread_deleted)
{
- printf("closing get_pos thread, %p\n", ev);
+ 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);
}
- printf("EX dispose %p\n", ev);
+ DBG("dispose %p", ev);
xine_dispose(ev->stream);
- printf("EX dispose evq %p\n", ev);
+ DBG("dispose evq %p", ev);
xine_event_dispose_queue(ev->queue);
- printf("EX close video drv %p\n", ev);
+ DBG("close video drv %p", ev);
if (ev->video) xine_close_video_driver(ev->decoder, ev->video);
- printf("EX wait for vo to go\n");
+ DBG("wait for vo to go");
while (ev->have_vo);
- printf("EX vo gone\n");
- printf("EX close audio drv %p\n", ev);
+ DBG("vo gone");
+ DBG("close audio drv %p", ev);
if (ev->audio) xine_close_audio_driver(ev->decoder, ev->audio);
- printf("EX xine exit %p\n", ev);
+ DBG("xine exit %p", ev);
xine_exit(ev->decoder);
- printf("EX DONE %p\n", ev);
+ DBG("DONE %p", ev);
close(ev->fd_write);
close(ev->fd_read);
close(ev->fd_ev_write);
char *file;
file = eev->xine_event;
- printf("OPN STREAM %s\n", file);
+ DBG("OPEN STREAM %s", file);
if (xine_open(ev->stream, file))
{
if (xine_get_pos_length(ev->stream, &pos_stream, &pos_time, &length_time))
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 */
{
- printf("EX done %p\n", ev);
+ DBG("done %p", ev);
em_frame_done(ev);
- printf("EX stop %p\n", ev);
+ DBG("stop %p", ev);
xine_stop(ev->stream);
- printf("EX close %p\n", ev);
+ DBG("close %p", ev);
xine_close(ev->stream);
- printf("EX close done %p\n", ev);
+ DBG("close done %p", ev);
_em_module_event(ev, 11);
}
break;
double pos;
pos = *((double *)eev->xine_event);
- if (ev->seeked_pos != ev->seek_to_pos)
- {
- 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);
- ev->seeked_pos = ev->seek_to_pos;
- }
+ 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;
break;
case 10: /* vol */
{
- double vol;
-
- vol = *((double *)eev->xine_event);
- if (vol < 0.0) vol = 0.0;
- if (vol > 1.0) vol = 1.0;
- xine_set_param(ev->stream, XINE_PARAM_AUDIO_VOLUME, vol * 100);
+ xine_set_param(ev->stream, XINE_PARAM_AUDIO_VOLUME, ev->volume * 100);
_em_module_event(ev, 10);
}
break;
new_ev->xine_event = arg;
buf[0] = data;
buf[1] = new_ev;
- write(ev->fd_slave_write, buf, sizeof(buf));
+ if (write(ev->fd_slave_write, buf, sizeof(buf)) < 0) perror("write");
}
static unsigned char
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;
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;
ev = (Emotion_Xine_Video *)ef;
ev->closing = 1;
ev->delete_me = 1;
- printf("EXM del fds %p\n", ev);
+ 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);
- printf("EXM done %p\n", ev);
+ DBG("done %p", ev);
return 1;
}
static unsigned char
-em_file_open(const char *file, Evas_Object *obj, void *ef)
+em_file_open(const char *file, Evas_Object *obj __UNUSED__, void *ef)
{
Emotion_Xine_Video *ev;
double *ppos;
ev = (Emotion_Xine_Video *)ef;
- if (pos == ev->seek_to_pos) return;
ppos = malloc(sizeof(double));
*ppos = pos;
- ev->seek_to_pos = pos;
_em_slave_event(ev, 6, ppos);
}
-static void
-em_vis_set(void *ef,
- Emotion_Vis vis)
+static double
+em_len_get(void *ef)
{
Emotion_Xine_Video *ev;
ev = (Emotion_Xine_Video *)ef;
- if (ev->vis == vis) return;
- ev->vis = vis;
+ return ev->len;
}
static double
-em_len_get(void *ef)
+em_buffer_size_get(void *ef)
{
Emotion_Xine_Video *ev;
ev = (Emotion_Xine_Video *)ef;
- return ev->len;
+ return ev->buffer;
}
static int
}
static int
-em_fps_den_get(void *ef)
+em_fps_den_get(void *ef __UNUSED__)
{
- Emotion_Xine_Video *ev;
-
- ev = (Emotion_Xine_Video *)ef;
return 10000;
}
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)
{
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)
{
}
static int
-em_yuv_rows_get(void *ef, int w, int h, unsigned char **yrows, unsigned char **urows, unsigned char **vrows)
+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;
}
static void
-em_event_mouse_button_feed(void *ef, int button, int x, int y)
+em_event_mouse_button_feed(void *ef, int button __UNUSED__, int x, int y)
{
Emotion_Xine_Video *ev;
xine_event_t xine_event;
}
static const char *
-em_video_channel_name_get(void *ef, int channel)
+em_video_channel_name_get(void *ef __UNUSED__, int channel __UNUSED__)
{
- Emotion_Xine_Video *ev;
-
- ev = (Emotion_Xine_Video *)ef;
return NULL;
}
em_audio_channel_volume_set(void *ef, double vol)
{
Emotion_Xine_Video *ev;
- double *ppos;
+ if (vol < 0.0) vol = 0.0;
+ else if (vol > 1.0) vol = 1.0;
+
ev = (Emotion_Xine_Video *)ef;
- ppos = malloc(sizeof(double));
- *ppos = vol;
- _em_slave_event(ev, 10, ppos);
+ ev->volume = vol;
+ _em_slave_event(ev, 10, NULL);
}
static double
Emotion_Xine_Video *ev;
ev = (Emotion_Xine_Video *)ef;
- if (ev->opening || (!ev->play_ok)) return 0;
- return (double)xine_get_param(ev->stream, XINE_PARAM_AUDIO_VOLUME) / 100.0;
+ 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
}
static void
-em_chapter_set(void *ef, int chapter)
+em_chapter_set(void *ef __UNUSED__, int chapter __UNUSED__)
{
- Emotion_Xine_Video *ev;
-
- ev = (Emotion_Xine_Video *)ef;
}
static int
-em_chapter_get(void *ef)
+em_chapter_get(void *ef __UNUSED__)
{
- Emotion_Xine_Video *ev;
-
- ev = (Emotion_Xine_Video *)ef;
return 0;
}
static const char *
-em_chapter_name_get(void *ef, int chapter)
+em_chapter_name_get(void *ef __UNUSED__, int chapter __UNUSED__)
{
- Emotion_Xine_Video *ev;
-
- ev = (Emotion_Xine_Video *)ef;
return NULL;
}
static void
-em_speed_set(void *ef, double speed)
+em_speed_set(void *ef __UNUSED__, double speed __UNUSED__)
{
- Emotion_Xine_Video *ev;
-
- ev = (Emotion_Xine_Video *)ef;
}
static double
-em_speed_get(void *ef)
+em_speed_get(void *ef __UNUSED__)
{
- Emotion_Xine_Video *ev;
-
- ev = (Emotion_Xine_Video *)ef;
return 1.0;
}
return NULL;
}
-static int
+static Eina_Bool
_em_fd_active(void *data, Ecore_Fd_Handler *fdh)
{
void *buf;
int fd, len;
Emotion_Xine_Video_Frame *fr;
- Emotion_Xine_Video *ev;
- ev = data;
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)
}
}
}
- return 1;
+ return EINA_TRUE;
+ data = NULL;
}
static void
}
buf[0] = data;
buf[1] = new_ev;
- write(ev->fd_ev_write, buf, sizeof(buf));
+ if (write(ev->fd_ev_write, buf, sizeof(buf)) < 0) perror("write");
}
static void
new_ev->type = -1;
buf[0] = data;
buf[1] = new_ev;
- write(ev->fd_ev_write, buf, sizeof(buf));
+ if (write(ev->fd_ev_write, buf, sizeof(buf)) < 0) perror("write");
}
-static int
-_em_fd_ev_active(void *data, Ecore_Fd_Handler *fdh)
+static Eina_Bool
+_em_audio_only_poller(void *data)
{
Emotion_Xine_Video *ev;
- int fd, len;
- void *buf[2];
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];
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 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;
}
}
break;
case XINE_EVENT_FRAME_FORMAT_CHANGE:
- {
- xine_format_change_data_t *e;
-
- e = (xine_format_change_data_t *)eev->xine_event;
- }
break;
case XINE_EVENT_UI_MESSAGE:
{
- xine_ui_message_data_t *e;
-
- e = (xine_ui_message_data_t *)eev->xine_event;
- printf("EV: UI Message [FIXME: break this out to emotion api]\n");
+ 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:
{
- xine_audio_level_data_t *e;
-
- e = (xine_audio_level_data_t *)eev->xine_event;
_emotion_audio_level_change(ev->obj);
- printf("EV: Audio Level [FIXME: break this out to emotion api]\n");
+ WRN("Audio Level [FIXME: break this out to emotion api]");
// e->left (0->100)
// e->right
// e->mute
xine_progress_data_t *e;
e = (xine_progress_data_t *)eev->xine_event;
- printf("PROGRESS: %i\n", e->percent);
+ 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:
+ case XINE_EVENT_MRL_REFERENCE_EXT:
{
- xine_mrl_reference_data_t *e;
+ xine_mrl_reference_data_ext_t *e;
- e = (xine_mrl_reference_data_t *)eev->xine_event;
+ e = (xine_mrl_reference_data_ext_t *)eev->xine_event;
_emotion_file_ref_set(ev->obj, e->mrl, e->alternative);
}
break;
xine_dropped_frames_t *e;
e = (xine_dropped_frames_t *)eev->xine_event;
- printf("EV: Dropped Frames (skipped %i) (discarded %i) [FIXME: break this out to the emotion api]\n", e->skipped_frames, e->discarded_frames);
+ 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:
- // printf("EV: unknown event type %i\n", eev->type);
+ // DBG("unknown event type %i", eev->type);
break;
}
}
free(eev);
}
}
- return 1;
+ return EINA_TRUE;
}
static void *
}
}
ev->get_poslen = 0;
- //printf("get pos %3.3f\n", ev->pos);
+ _em_module_event(ev, 15); /* event - getpos done */
+ //DBG("get pos %3.3f", ev->pos);
}
if (ev->delete_me)
{
static void
_em_get_pos_len(Emotion_Xine_Video *ev)
{
- if (ev->get_poslen) return;
+ 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));
em_stop, /* stop */
em_size_get, /* size_get */
em_pos_set, /* pos_set */
- em_vis_set, /* vis_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_speed_get, /* speed_get */
em_eject, /* eject */
em_meta_get, /* meta_get */
-
+ NULL, /* priority_set */
+ NULL, /* priority_get */
NULL /* handle */
};
-unsigned char
+static Eina_Bool
module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
{
if (!module)
- return 0;
-
+ 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 0;
+ return EINA_FALSE;
*module = &em_module;
- return 1;
+ return EINA_TRUE;
}
-void
-module_close(Emotion_Video_Module *module, void *video)
+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)
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);
- printf("has_chapters = %i\n", has_chapters);
- printf("max_spu = %i\n", max_spu);
- printf("max_audio = %i\n", max_audio);
- printf("video_channels = %i\n", video_channels);
- printf("video_streams = %i\n", video_streams);
- printf("video_seekable = %i\n", video_seekable);
- printf("title = %s\n", title);
- printf("comment = %s\n", comment);
- printf("artist = %s\n", artist);
- printf("genre = %s\n", genre);
- printf("album = %s\n", album);
- printf("year = %s\n", year);
- printf("cdindex_discid = %s\n", cdindex_discid);
- printf("video_channel = %i\n", video_channel);
- printf("audio_channel = %i\n", audio_channel);
- printf("spu_channels = %i\n", spu_channel);
- printf("video_ratio = %i\n", video_ratio);
- printf("audio_mode = %i\n", 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;
- printf(" AUDIO %i = ", i);
if (xine_get_audio_lang(ev->stream, i, lang))
- printf("%s\n", lang);
- else
- printf("NONE\n");
+ 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;
- printf(" SPU %i = ", i);
if (xine_get_spu_lang(ev->stream, i, lang))
- printf("%s\n", lang);
- else
- printf("NONE\n");
+ eina_strlcpy(buf, lang, sizeof(buf));
+ DBG(" SPU %i = %s", i, buf);
}
}
}
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;
volatile int spu_channel;
volatile int audio_channel;
volatile int video_channel;
- volatile double seek_to_pos;
- volatile double seeked_pos;
volatile int fq;
Emotion_Vis vis;
- int fd_read;
+ 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;
- unsigned char opt_no_video : 1;
- unsigned char opt_no_audio : 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;
int mtype;
};
-unsigned char module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt);
-void module_close(Emotion_Video_Module *module, void *video);
+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
/***************************************************************************/
/*** emotion xine display engine ***/
/***************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <Eina.h>
+#include <Evas.h>
+#include <Ecore.h>
+
+#include "Emotion.h"
#include "emotion_private.h"
#include "emotion_xine.h"
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 void *
-_emotion_class_init(xine_t *xine, void *visual)
+_emotion_class_init(xine_t *xine, void *visual __UNUSED__)
{
Emotion_Class *cl;
-// printf("emotion: _emotion_class_init()\n");
- cl = (Emotion_Class *) xine_xmalloc(sizeof(Emotion_Class));
+// 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;
}
static char *
-_emotion_class_identifier_get(video_driver_class_t *driver_class)
+_emotion_class_identifier_get(video_driver_class_t *driver_class __UNUSED__)
{
- Emotion_Class *cl;
-
- cl = (Emotion_Class *)driver_class;
return "emotion";
}
static char *
-_emotion_class_description_get(video_driver_class_t *driver_class)
+_emotion_class_description_get(video_driver_class_t *driver_class __UNUSED__)
{
- Emotion_Class *cl;
-
- cl = (Emotion_Class *)driver_class;
return "Emotion xine video output plugin";
}
cl = (Emotion_Class *)driver_class;
/* visual here is the data ptr passed to xine_open_video_driver() */
-// printf("emotion: _emotion_open()\n");
- dv = (Emotion_Driver *)xine_xmalloc(sizeof(Emotion_Driver));
+// DBG("");
+ dv = (Emotion_Driver *)malloc(sizeof(Emotion_Driver));
if (!dv) return NULL;
dv->config = cl->config;
dv->vo_driver.redraw_needed = _emotion_redraw;
dv->ev = (Emotion_Xine_Video *)visual;
dv->ev->have_vo = 1;
- printf("emotion: _emotion_open = %p\n", &dv->vo_driver);
+ DBG("vo_driver = %p", &dv->vo_driver);
return &dv->vo_driver;
}
dv = (Emotion_Driver *)vo_driver;
dv->ev->have_vo = 0;
- printf("emotion: _emotion_dispose(%p)\n", dv);
+ DBG("vo_driver = %p", dv);
free(dv);
}
/***************************************************************************/
static int
-_emotion_redraw(vo_driver_t *vo_driver)
+_emotion_redraw(vo_driver_t *vo_driver __UNUSED__)
{
- Emotion_Driver *dv;
-
- dv = (Emotion_Driver *)vo_driver;
-// printf("emotion: _emotion_redraw()\n");
+// DBG("");
return 0;
}
/***************************************************************************/
static uint32_t
-_emotion_capabilities_get(vo_driver_t *vo_driver)
+_emotion_capabilities_get(vo_driver_t *vo_driver __UNUSED__)
{
- Emotion_Driver *dv;
-
- dv = (Emotion_Driver *)vo_driver;
-// printf("emotion: _emotion_capabilities_get()\n");
+// DBG("");
return VO_CAP_YV12 | VO_CAP_YUY2;
}
/***************************************************************************/
static int
-_emotion_gui_data_exchange(vo_driver_t *vo_driver, int data_type, void *data)
+_emotion_gui_data_exchange(vo_driver_t *vo_driver __UNUSED__, int data_type, void *data __UNUSED__)
{
- Emotion_Driver *dv;
-
- dv = (Emotion_Driver *)vo_driver;
-// printf("emotion: _emotion_gui_data_exchange()\n");
+// DBG("");
switch (data_type)
{
case XINE_GUI_SEND_COMPLETION_EVENT:
Emotion_Driver *dv;
dv = (Emotion_Driver *)vo_driver;
-// printf("emotion: _emotion_property_set()\n");
+// DBG("");
switch (property)
{
case VO_PROP_ASPECT_RATIO:
if (value >= XINE_VO_ASPECT_NUM_RATIOS)
value = XINE_VO_ASPECT_AUTO;
-// printf("DRIVER RATIO SET %i!\n", value);
+// DBG("DRIVER RATIO SET %i!", value);
dv->ratio = value;
break;
default:
Emotion_Driver *dv;
dv = (Emotion_Driver *)vo_driver;
-// printf("emotion: _emotion_property_get()\n");
+// DBG("");
switch (property)
{
case VO_PROP_ASPECT_RATIO:
}
static void
-_emotion_property_min_max_get(vo_driver_t *vo_driver, int property, int *min, int *max)
+_emotion_property_min_max_get(vo_driver_t *vo_driver __UNUSED__, int property __UNUSED__, int *min, int *max)
{
- Emotion_Driver *dv;
-
- dv = (Emotion_Driver *)vo_driver;
-// printf("emotion: _emotion_property_min_max_get()\n");
+// DBG("");
*min = 0;
*max = 0;
}
/***************************************************************************/
static vo_frame_t *
-_emotion_frame_alloc(vo_driver_t *vo_driver)
+_emotion_frame_alloc(vo_driver_t *vo_driver __UNUSED__)
{
- Emotion_Driver *dv;
Emotion_Frame *fr;
- dv = (Emotion_Driver *)vo_driver;
-// printf("emotion: _emotion_frame_alloc()\n");
- fr = (Emotion_Frame *)xine_xmalloc(sizeof(Emotion_Frame));
+// DBG("");
+ fr = (Emotion_Frame *)calloc(1, sizeof(Emotion_Frame));
if (!fr) return NULL;
fr->vo_frame.base[0] = NULL;
Emotion_Frame *fr;
fr = (Emotion_Frame *)vo_frame;
-// printf("emotion: _emotion_frame_dispose()\n");
+// 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)
+_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 != width) || (fr->height != height) ||
+ if ((fr->width != (int)width) || (fr->height != (int)height) ||
(fr->format != format) || (!fr->vo_frame.base[0]))
{
-// printf("emotion: _emotion_frame_format_update()\n");
+// DBG("");
_emotion_frame_data_free(fr);
fr->width = width;
break;
}
if (((format == XINE_IMGFMT_YV12)
- && ((fr->vo_frame.base[0] == NULL)
- || (fr->vo_frame.base[1] == NULL)
- || (fr->vo_frame.base[2] == NULL)))
+ && ((!fr->vo_frame.base[0])
+ || (!fr->vo_frame.base[1])
+ || (!fr->vo_frame.base[2])))
|| ((format == XINE_IMGFMT_YUY2)
- && ((fr->vo_frame.base[0] == NULL)
- || (fr->frame.bgra_data == NULL))))
+ && ((!fr->vo_frame.base[0])
+ || (!fr->frame.bgra_data))))
{
_emotion_frame_data_free(fr);
}
dv = (Emotion_Driver *)vo_driver;
fr = (Emotion_Frame *)vo_frame;
-// printf("emotion: _emotion_frame_display()\n");
-// printf("EX VO: fq %i %p\n", dv->ev->fq, dv->ev);
+// 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;
- int ret;
if (dv->ev->closing) return;
if (fr->format == XINE_IMGFMT_YUY2)
buf = &(fr->frame);
fr->frame.timestamp = (double)fr->vo_frame.vpts / 90000.0;
- fr->frame.done_func = _emotion_frame_data_unlock;
+ fr->frame.done_func = (done_func_type)_emotion_frame_data_unlock;
fr->frame.done_data = fr;
-// printf("FRAME FOR %p\n", dv->ev);
- ret = write(dv->ev->fd_write, &buf, sizeof(void *));
-// printf("-- FRAME DEC %p == %i\n", fr->frame.obj, ret);
+// 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++;
}
}
static void
-_emotion_frame_field(vo_frame_t *vo_frame, int which_field)
+_emotion_frame_field(vo_frame_t *vo_frame __UNUSED__, int which_field __UNUSED__)
{
- Emotion_Frame *fr;
-
- fr = (Emotion_Frame *)vo_frame;
-// printf("emotion: _emotion_frame_field()\n");
+// DBG("");
}
/***************************************************************************/
static void
_emotion_frame_data_unlock(Emotion_Frame *fr)
{
-// printf("emotion: _emotion_frame_data_unlock()\n");
+// DBG("");
if (fr->in_use)
{
fr->vo_frame.free(&fr->vo_frame);
/***************************************************************************/
static void
-_emotion_overlay_begin(vo_driver_t *vo_driver, vo_frame_t *vo_frame, int changed)
+_emotion_overlay_begin(vo_driver_t *vo_driver __UNUSED__, vo_frame_t *vo_frame __UNUSED__, int changed __UNUSED__)
{
- Emotion_Driver *dv;
- Emotion_Frame *fr;
-
- dv = (Emotion_Driver *)vo_driver;
- fr = (Emotion_Frame *)vo_frame;
-// printf("emotion: _emotion_overlay_begin()\n");
+// DBG("");
}
static void
-_emotion_overlay_end(vo_driver_t *vo_driver, vo_frame_t *vo_frame)
+_emotion_overlay_end(vo_driver_t *vo_driver __UNUSED__, vo_frame_t *vo_frame __UNUSED__)
{
- Emotion_Driver *dv;
- Emotion_Frame *fr;
-
- dv = (Emotion_Driver *)vo_driver;
- fr = (Emotion_Frame *)vo_frame;
-// printf("emotion: _emotion_overlay_end()\n");
+// DBG("");
}
static void
-_emotion_overlay_blend(vo_driver_t *vo_driver, vo_frame_t *vo_frame, vo_overlay_t *vo_overlay)
+_emotion_overlay_blend(vo_driver_t *vo_driver __UNUSED__, vo_frame_t *vo_frame, vo_overlay_t *vo_overlay __UNUSED__)
{
- Emotion_Driver *dv;
Emotion_Frame *fr;
- dv = (Emotion_Driver *)vo_driver;
fr = (Emotion_Frame *)vo_frame;
-// printf("emotion: _emotion_overlay_blend()\n");
+// DBG("");
_emotion_overlay_blend_yuv(fr->vo_frame.base, vo_overlay,
fr->width, fr->height,
fr->vo_frame.pitches);