From: Jinkun Jang Date: Tue, 12 Mar 2013 16:53:14 +0000 (+0900) Subject: Tizen 2.1 base X-Git-Tag: accepted/tizen/20130607.213312~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c8e8e816d23e4c9f4434d25038c26ff5bb52feb9;p=profile%2Fmobile%2Femotion.git Tizen 2.1 base --- diff --git a/AUTHORS b/AUTHORS index 9ba33c3..c2579a8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,10 @@ -The Rasterman (Carsten Haitzler) -doursse (Vincent Torri) -captainigloo +Carsten Haitzler +Vincent Torri +Nicolas Aguirre +Sebastian Dransfeld +Cedric Bail +Rafael Antognolli +Jérôme Pinot +Pierre Le Magourou +Hugo Camboulive +Sohyun Kim diff --git a/COPYING b/COPYING index 474fcc5..aab8362 100644 --- a/COPYING +++ b/COPYING @@ -1,28 +1,25 @@ -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. diff --git a/ChangeLog b/ChangeLog index e47b581..af65492 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,36 +1,60 @@ -2007-10-31 Vincent Torri - - * 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 - - * 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. diff --git a/Makefile.am b/Makefile.am index 6d2fd00..248f9bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,22 +2,51 @@ 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 diff --git a/NEWS b/NEWS index e69de29..7202b33 100644 --- a/NEWS +++ b/NEWS @@ -0,0 +1,26 @@ +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: + diff --git a/README b/README index c64cc15..301dbaa 100644 --- a/README +++ b/README @@ -1 +1,22 @@ -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 diff --git a/TC/README b/TC/README new file mode 100644 index 0000000..d466648 --- /dev/null +++ b/TC/README @@ -0,0 +1,14 @@ +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. diff --git a/TC/_export_env.sh b/TC/_export_env.sh new file mode 100755 index 0000000..4215842 --- /dev/null +++ b/TC/_export_env.sh @@ -0,0 +1,40 @@ +# 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 diff --git a/TC/build.sh b/TC/build.sh new file mode 100755 index 0000000..28a7d2a --- /dev/null +++ b/TC/build.sh @@ -0,0 +1,23 @@ +#!/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 + diff --git a/TC/clean.sh b/TC/clean.sh new file mode 100755 index 0000000..e171e93 --- /dev/null +++ b/TC/clean.sh @@ -0,0 +1,11 @@ +#!/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` diff --git a/TC/emotion/common.h b/TC/emotion/common.h new file mode 100644 index 0000000..1b4f989 --- /dev/null +++ b/TC/emotion/common.h @@ -0,0 +1,65 @@ +#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 diff --git a/TC/emotion/emotion_private.h b/TC/emotion/emotion_private.h new file mode 100644 index 0000000..6595436 --- /dev/null +++ b/TC/emotion/emotion_private.h @@ -0,0 +1,130 @@ +#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 diff --git a/TC/emotion/test.avi b/TC/emotion/test.avi new file mode 100644 index 0000000..b60a3d7 Binary files /dev/null and b/TC/emotion/test.avi differ diff --git a/TC/emotion/tslist b/TC/emotion/tslist new file mode 100644 index 0000000..f2fb627 --- /dev/null +++ b/TC/emotion/tslist @@ -0,0 +1,56 @@ +/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 diff --git a/TC/emotion/utc_UIFW_emotion_audio_level_change.c b/TC/emotion/utc_UIFW_emotion_audio_level_change.c new file mode 100644 index 0000000..de4a19a --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_audio_level_change.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_channels_change.c b/TC/emotion/utc_UIFW_emotion_channels_change.c new file mode 100644 index 0000000..9956c83 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_channels_change.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_decode_stop.c b/TC/emotion/utc_UIFW_emotion_decode_stop.c new file mode 100644 index 0000000..01a63a9 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_decode_stop.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_file_ref_set.c b/TC/emotion/utc_UIFW_emotion_file_ref_set.c new file mode 100644 index 0000000..6831a47 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_file_ref_set.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_frame_new.c b/TC/emotion/utc_UIFW_emotion_frame_new.c new file mode 100644 index 0000000..ab8c131 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_frame_new.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_frame_refill.c b/TC/emotion/utc_UIFW_emotion_frame_refill.c new file mode 100644 index 0000000..4225ad3 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_frame_refill.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_frame_resize.c b/TC/emotion/utc_UIFW_emotion_frame_resize.c new file mode 100644 index 0000000..3350fa6 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_frame_resize.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_init.c b/TC/emotion/utc_UIFW_emotion_init.c new file mode 100644 index 0000000..1570acc --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_init.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_module_register.c b/TC/emotion/utc_UIFW_emotion_module_register.c new file mode 100644 index 0000000..92292ae --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_module_register.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_module_unregister.c b/TC/emotion/utc_UIFW_emotion_module_unregister.c new file mode 100644 index 0000000..a55f0f5 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_module_unregister.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_add.c b/TC/emotion/utc_UIFW_emotion_object_add.c new file mode 100644 index 0000000..5b4142a --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_add.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/TC/emotion/utc_UIFW_emotion_object_audio_channel_count.c b/TC/emotion/utc_UIFW_emotion_object_audio_channel_count.c new file mode 100644 index 0000000..979b2e0 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_audio_channel_count.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_audio_mute_set_get.c b/TC/emotion/utc_UIFW_emotion_object_audio_mute_set_get.c new file mode 100644 index 0000000..63b8f48 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_audio_mute_set_get.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_audio_volume_set_get.c b/TC/emotion/utc_UIFW_emotion_object_audio_volume_set_get.c new file mode 100644 index 0000000..7cc40f4 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_audio_volume_set_get.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_bg_color_set.c b/TC/emotion/utc_UIFW_emotion_object_bg_color_set.c new file mode 100644 index 0000000..9e5e468 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_bg_color_set.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_border_set.c b/TC/emotion/utc_UIFW_emotion_object_border_set.c new file mode 100644 index 0000000..914fd20 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_border_set.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_event_simple_send.c b/TC/emotion/utc_UIFW_emotion_object_event_simple_send.c new file mode 100644 index 0000000..60f073b --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_event_simple_send.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_file_set_get.c b/TC/emotion/utc_UIFW_emotion_object_file_set_get.c new file mode 100644 index 0000000..a299b02 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_file_set_get.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/TC/emotion/utc_UIFW_emotion_object_image_get.c b/TC/emotion/utc_UIFW_emotion_object_image_get.c new file mode 100644 index 0000000..63894a5 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_image_get.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_init.c b/TC/emotion/utc_UIFW_emotion_object_init.c new file mode 100644 index 0000000..6ce39bf --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_init.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/TC/emotion/utc_UIFW_emotion_object_keep_aspect_set.c b/TC/emotion/utc_UIFW_emotion_object_keep_aspect_set.c new file mode 100644 index 0000000..b96dfbf --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_keep_aspect_set.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/TC/emotion/utc_UIFW_emotion_object_last_position_save_load.c b/TC/emotion/utc_UIFW_emotion_object_last_position_save_load.c new file mode 100644 index 0000000..53c0cb4 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_last_position_save_load.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_meta_info_get.c b/TC/emotion/utc_UIFW_emotion_object_meta_info_get.c new file mode 100644 index 0000000..5ea4854 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_meta_info_get.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_module_option_set.c b/TC/emotion/utc_UIFW_emotion_object_module_option_set.c new file mode 100644 index 0000000..8cd4821 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_module_option_set.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_play_length_get.c b/TC/emotion/utc_UIFW_emotion_object_play_length_get.c new file mode 100644 index 0000000..d38ff5e --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_play_length_get.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_play_set_get.c b/TC/emotion/utc_UIFW_emotion_object_play_set_get.c new file mode 100644 index 0000000..8375783 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_play_set_get.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/TC/emotion/utc_UIFW_emotion_object_play_speed_set_get.c b/TC/emotion/utc_UIFW_emotion_object_play_speed_set_get.c new file mode 100644 index 0000000..5dab151 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_play_speed_set_get.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_position_set_get.c b/TC/emotion/utc_UIFW_emotion_object_position_set_get.c new file mode 100644 index 0000000..fefedce --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_position_set_get.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_progress_info_get.c b/TC/emotion/utc_UIFW_emotion_object_progress_info_get.c new file mode 100644 index 0000000..795604f --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_progress_info_get.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_progress_status_get.c b/TC/emotion/utc_UIFW_emotion_object_progress_status_get.c new file mode 100644 index 0000000..e94611e --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_progress_status_get.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_ratio_get.c b/TC/emotion/utc_UIFW_emotion_object_ratio_get.c new file mode 100644 index 0000000..779859f --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_ratio_get.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_ref_file_get.c b/TC/emotion/utc_UIFW_emotion_object_ref_file_get.c new file mode 100644 index 0000000..3103059 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_ref_file_get.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_ref_num_get.c b/TC/emotion/utc_UIFW_emotion_object_ref_num_get.c new file mode 100644 index 0000000..d337125 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_ref_num_get.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_seekable_get.c b/TC/emotion/utc_UIFW_emotion_object_seekable_get.c new file mode 100644 index 0000000..366b216 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_seekable_get.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/TC/emotion/utc_UIFW_emotion_object_size_get.c b/TC/emotion/utc_UIFW_emotion_object_size_get.c new file mode 100644 index 0000000..93fceec --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_size_get.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_smooth_scale_set.c b/TC/emotion/utc_UIFW_emotion_object_smooth_scale_set.c new file mode 100644 index 0000000..7907cf4 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_smooth_scale_set.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_spu_button_count_get.c b/TC/emotion/utc_UIFW_emotion_object_spu_button_count_get.c new file mode 100644 index 0000000..9dc0528 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_spu_button_count_get.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_spu_button_get.c b/TC/emotion/utc_UIFW_emotion_object_spu_button_get.c new file mode 100644 index 0000000..097858f --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_spu_button_get.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_spu_channel_count.c b/TC/emotion/utc_UIFW_emotion_object_spu_channel_count.c new file mode 100644 index 0000000..be764db --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_spu_channel_count.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_title_get.c b/TC/emotion/utc_UIFW_emotion_object_title_get.c new file mode 100644 index 0000000..b9772e0 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_title_get.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_video_channel_count.c b/TC/emotion/utc_UIFW_emotion_object_video_channel_count.c new file mode 100644 index 0000000..7e1a4d1 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_video_channel_count.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_video_mute_set_get.c b/TC/emotion/utc_UIFW_emotion_object_video_mute_set_get.c new file mode 100644 index 0000000..6666696 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_video_mute_set_get.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_vis_set_get.c b/TC/emotion/utc_UIFW_emotion_object_vis_set_get.c new file mode 100644 index 0000000..40d64c5 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_vis_set_get.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_object_vis_supported.c b/TC/emotion/utc_UIFW_emotion_object_vis_supported.c new file mode 100644 index 0000000..722ec89 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_object_vis_supported.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_open_done.c b/TC/emotion/utc_UIFW_emotion_open_done.c new file mode 100644 index 0000000..a8de5aa --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_open_done.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_playback_finished.c b/TC/emotion/utc_UIFW_emotion_playback_finished.c new file mode 100644 index 0000000..b752e3b --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_playback_finished.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_playback_started.c b/TC/emotion/utc_UIFW_emotion_playback_started.c new file mode 100644 index 0000000..2996028 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_playback_started.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_progress_set.c b/TC/emotion/utc_UIFW_emotion_progress_set.c new file mode 100644 index 0000000..91c58ff --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_progress_set.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_seek_done.c b/TC/emotion/utc_UIFW_emotion_seek_done.c new file mode 100644 index 0000000..4884033 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_seek_done.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_shutdown.c b/TC/emotion/utc_UIFW_emotion_shutdown.c new file mode 100644 index 0000000..656db50 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_shutdown.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_spu_button_num_set.c b/TC/emotion/utc_UIFW_emotion_spu_button_num_set.c new file mode 100644 index 0000000..ff296dd --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_spu_button_num_set.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_spu_button_set.c b/TC/emotion/utc_UIFW_emotion_spu_button_set.c new file mode 100644 index 0000000..34a316b --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_spu_button_set.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_title_set.c b/TC/emotion/utc_UIFW_emotion_title_set.c new file mode 100644 index 0000000..035fed3 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_title_set.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_video_get.c b/TC/emotion/utc_UIFW_emotion_video_get.c new file mode 100644 index 0000000..397f906 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_video_get.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_video_pos_update.c b/TC/emotion/utc_UIFW_emotion_video_pos_update.c new file mode 100644 index 0000000..f75b8f3 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_video_pos_update.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/emotion/utc_UIFW_emotion_webcam_custom_get.c b/TC/emotion/utc_UIFW_emotion_webcam_custom_get.c new file mode 100644 index 0000000..d5e00c0 --- /dev/null +++ b/TC/emotion/utc_UIFW_emotion_webcam_custom_get.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include +#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); +} + diff --git a/TC/execute.sh b/TC/execute.sh new file mode 100755 index 0000000..ce3421b --- /dev/null +++ b/TC/execute.sh @@ -0,0 +1,17 @@ +#!/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 + diff --git a/TC/tet_scen b/TC/tet_scen new file mode 100644 index 0000000..2309232 --- /dev/null +++ b/TC/tet_scen @@ -0,0 +1,8 @@ +all + ^EMOTION +##### Scenarios for TEST ##### + +# Test scenario + +EMOTION + :include:/emotion/tslist diff --git a/TC/tetbuild.cfg b/TC/tetbuild.cfg new file mode 100755 index 0000000..f7eda55 --- /dev/null +++ b/TC/tetbuild.cfg @@ -0,0 +1,5 @@ +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? diff --git a/TC/tetclean.cfg b/TC/tetclean.cfg new file mode 100755 index 0000000..02d7030 --- /dev/null +++ b/TC/tetclean.cfg @@ -0,0 +1,5 @@ +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 diff --git a/TC/tetexec.cfg b/TC/tetexec.cfg new file mode 100755 index 0000000..ef3e452 --- /dev/null +++ b/TC/tetexec.cfg @@ -0,0 +1,5 @@ +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 ? diff --git a/autogen.sh b/autogen.sh index 995ff2f..00116ea 100755 --- a/autogen.sh +++ b/autogen.sh @@ -4,6 +4,7 @@ rm -rf autom4te.cache rm -f aclocal.m4 ltmain.sh touch README +touch ABOUT-NLS echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1 echo "Running autoheader..." ; autoheader || exit 1 @@ -11,6 +12,28 @@ echo "Running autoconf..." ; autoconf || exit 1 echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1 echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1 +W=0 + +rm -f config.cache-env.tmp +echo "OLD_PARM=\"$@\"" >> config.cache-env.tmp +echo "OLD_CFLAGS=\"$CFLAGS\"" >> config.cache-env.tmp +echo "OLD_PATH=\"$PATH\"" >> config.cache-env.tmp +echo "OLD_PKG_CONFIG_PATH=\"$PKG_CONFIG_PATH\"" >> config.cache-env.tmp +echo "OLD_LDFLAGS=\"$LDFLAGS\"" >> config.cache-env.tmp + +cmp config.cache-env.tmp config.cache-env >> /dev/null +if [ $? -ne 0 ]; then + W=1; +fi + +if [ $W -ne 0 ]; then + echo "Cleaning configure cache..."; + rm -f config.cache config.cache-env + mv config.cache-env.tmp config.cache-env +else + rm -f config.cache-env.tmp +fi + if [ -z "$NOCONFIGURE" ]; then - ./configure "$@" + ./configure -C "$@" fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..13b09c2 --- /dev/null +++ b/configure.ac @@ -0,0 +1,370 @@ +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +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 +#include + ]], + [[ +fprintf(stdout, "%i\n", V4L2_CAP_VIDEO_CAPTURE); + ]])], + [ + AC_DEFINE(HAVE_V4L2, 1, [Define to 1 if you have Video4Linux 2 available]) + have_v4l2="yes" + ], + [have_v4l2="no"]) +AC_MSG_RESULT([${have_v4l2}]) + +### Checks for types + + +### Checks for structures + + +### Checks for compiler characteristics +AC_C_BIGENDIAN +AC_C___ATTRIBUTE__ + +EFL_EMOTION_BUILD="" +case "$host_os" in + mingw32ce*) + EMOTION_CPPFLAGS="-D_WIN32_WCE=0x0420" + EFL_EMOTION_BUILD="-DEFL_EMOTION_BUILD" + ;; + mingw*) + EMOTION_CPPFLAGS="-D_WIN32_WINNT=0x0501" + EFL_EMOTION_BUILD="-DEFL_EMOTION_BUILD" + ;; +esac +AC_SUBST(EFL_EMOTION_BUILD) +AC_SUBST(EMOTION_CPPFLAGS) + + +### Checks for linker characteristics + +# use --enable-auto-import on Windows + +lt_enable_auto_import="" +case "$host_os" in + mingw*) + lt_enable_auto_import="-Wl,--enable-auto-import" + ;; +esac +AC_SUBST(lt_enable_auto_import) + + +### Checks for library functions +AC_FUNC_ALLOCA + + +### Modules + +EMOTION_CHECK_MODULE([Xine], [${want_xine}]) +EMOTION_CHECK_MODULE([Gstreamer], [${want_gstreamer}]) +EMOTION_CHECK_MODULE([Generic], [${want_generic}]) + +EMOTION_CHECK_GENERIC_PLAYER([VLC], [${want_generic_vlc}]) + +if test "x${enable_xine}" = "xno" && test "x${enable_gstreamer}" = "xno" && test "x${enable_generic}" = "xno" ; then + AC_MSG_ERROR([Xine, Gstreamer or Generic backends must be selected to build Emotion]) +fi + +# Check if gstreamer X Overlay is available +build_xoverlay="no" +if test "x${enable_gstreamer}" = "xyes" ; then + PKG_CHECK_MODULES([GSTREAMER_INTERFACE], + [gstreamer-interfaces-0.10 >= 0.10.34], + [build_xoverlay="yes"], + [build_xoverlay="no"]) + if test "x${build_xoverlay}" = "xyes" ; then + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS ${GSTREAMER_CFLAGS} ${GSTREAMER_INTERFACE_CFLAGS}" + AC_CHECK_HEADER([gst/interfaces/xoverlay.h], + [ + AC_DEFINE(HAVE_XOVERLAY_H, 1, [Build with Gstreamer Xoverlay support]) + build_xoverlay="yes" + ], + [build_xoverlay="no"]) + CPPFLAGS=$save_CPPFLAGS + + save_LDFLAGS=${LDFLAGS} + LDFLAGS="${LDFLAGS} ${GSTREAMER_INTERFACES}" + AC_CHECK_LIB([gstinterfaces-0.10], + [gst_x_overlay_set_window_handle], + [AC_DEFINE([HAVE_X_OVERLAY_SET], [1], [Use gst_x_overlay_set_window_handle instead of old deprecated gst_x_overlay_set_xwindow_id])]) + LDFLAGS=$sava_LDFLAGS + fi +fi + +### install and build examples + +EFL_CHECK_BUILD_EXAMPLES([enable_build_examples="yes"], [enable_build_examples="no"]) +EFL_CHECK_INSTALL_EXAMPLES([enable_install_examples="yes"], [enable_install_examples="no"]) + +AC_SUBST(requirement_emotion) + +AC_OUTPUT([ +Makefile +emotion.pc +emotion.spec +src/Makefile +src/lib/Makefile +src/modules/Makefile +src/modules/xine/Makefile +src/modules/gstreamer/Makefile +src/modules/generic/Makefile +src/edje_external/Makefile +src/generic_players/Makefile +src/generic_players/vlc/Makefile +src/bin/Makefile +src/examples/Makefile +doc/Makefile +doc/Doxyfile +data/Makefile +]) + + +##################################################################### +## Info + +echo +echo +echo +echo "------------------------------------------------------------------------" +echo "$PACKAGE $VERSION" +echo "------------------------------------------------------------------------" +echo +echo "Configuration Options Summary:" +echo +echo " Modules:" +echo " Xine...............: ${enable_xine}" +echo " Gstreamer..........: ${enable_gstreamer} (X: ${have_ecore_x}/${build_xoverlay})" +echo " Generic............: ${enable_generic}" + +if test "x${enable_generic}" = "xyes" || test "x${enable_generic}" = "xstatic"; then +echo +echo " Generic Players:" +echo " VLC................: ${enable_generic_vlc}" +fi + +echo +echo " Build emotion_test...: $have_emotion_test" +echo " edje_cc..............: ${edje_cc}" +echo +echo " Edje EXTERNAL support: ${have_edje_external}" +echo +echo " Eio..................: ${have_eio}" +echo " V4L2.................: ${have_v4l2}" +echo +echo "Documentation..........: ${build_doc}" +echo "Examples.............: ${enable_build_examples}" +echo "Examples installed...: ${enable_install_examples}" +echo +echo "Compilation............: make (or gmake)" +echo " CPPFLAGS.............: $CPPFLAGS" +echo " CFLAGS...............: $CFLAGS" +echo " LDFLAGS..............: $LDFLAGS" +echo +echo "Installation...........: make install (as root if needed, with 'su' or 'sudo')" +echo " prefix...............: $prefix" +echo +if test "x${have_static_module}" = "xyes" ; then +echo -e "\0033\01331;31mWarning\0033\01331;0m: You are trying to link statically one or more modules to Emotion." +echo " You must know what you are doing, or else you will have a lot of problems." +echo " And asparagus will disappear from the earth." +echo " Think about that." +echo +fi diff --git a/data/Makefile.am b/data/Makefile.am index 5121518..6e5ce6f 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,11 +1,20 @@ 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 \ @@ -31,13 +40,18 @@ video_frame_right.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 diff --git a/data/e_logo.png b/data/e_logo.png index 54100d5..0b79b69 100644 Binary files a/data/e_logo.png and b/data/e_logo.png differ diff --git a/data/icon.edc b/data/icon.edc new file mode 100644 index 0000000..0a3ea3d --- /dev/null +++ b/data/icon.edc @@ -0,0 +1,14 @@ +collections { + images.image: "e_logo.png" COMP; + group { name: "icon"; + min: 20 10; + parts { + part { name: "icon"; type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "e_logo.png"; + } + } + } + } +} diff --git a/data/theme.edc b/data/theme.edc index a3c28a0..63e732d 100644 --- a/data/theme.edc +++ b/data/theme.edc @@ -28,10 +28,6 @@ images { image: "pnl.png" COMP; } -fonts { - font: "Vera.ttf" "Vera"; -} - collections { group { name: "background"; @@ -613,7 +609,7 @@ collections { color2: 0 0 0 255; text { text: "Video Progress"; - font: "Vera"; + font: "Sans"; size: 6; align: 0.0 1.0; }; @@ -869,7 +865,494 @@ collections { 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; }; @@ -1116,7 +1599,7 @@ collections { 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; diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..80b0bb3 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,99 @@ +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 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 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 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 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 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 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 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 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 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 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 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 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 Mon, 14 Nov 2011 18:54:14 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..1e8b314 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +6 diff --git a/debian/control b/debian/control index ed7a589..fe0d60e 100644 --- a/debian/control +++ b/debian/control @@ -1,27 +1,30 @@ Source: emotion Priority: optional Section: libs -Maintainer: Falko Schmidt -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 , Myoungwoon Kim , Jeonghyun Yun +Original-Maintainer: Falko Schmidt +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. @@ -29,35 +32,14 @@ Description: Headers, static libraries and documentation for Emotion 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. diff --git a/debian/libemotion0-dev.install b/debian/libemotion0-dev.install new file mode 100644 index 0000000..b8d218e --- /dev/null +++ b/debian/libemotion0-dev.install @@ -0,0 +1,4 @@ +debian/tmp/usr/include/* +debian/tmp/usr/lib/pkgconfig/* +debian/tmp/usr/lib/*.a +debian/tmp/usr/lib/*.so diff --git a/debian/libemotion0-gstreamer.install b/debian/libemotion0-gstreamer.install new file mode 100644 index 0000000..8494825 --- /dev/null +++ b/debian/libemotion0-gstreamer.install @@ -0,0 +1 @@ +debian/tmp/usr/lib/emotion/*gstreamer*.so diff --git a/debian/libemotion0.install b/debian/libemotion0.install index 7945678..c688e77 100644 --- a/debian/libemotion0.install +++ b/debian/libemotion0.install @@ -1 +1,3 @@ debian/tmp/usr/lib/libemotion.so.* +debian/tmp/usr/bin/emotion_* +debian/tmp/usr/share/emotion/data/theme.edj diff --git a/debian/rules b/debian/rules old mode 100644 new mode 100755 index 378c8aa..49e465a --- a/debian/rules +++ b/debian/rules @@ -3,7 +3,9 @@ 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 diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 0000000..907be04 --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,138 @@ +PROJECT_NAME = Emotion +PROJECT_NUMBER = @PACKAGE_VERSION@ +OUTPUT_DIRECTORY = . +INPUT = @top_srcdir@/src/lib \ + @srcdir@/examples.dox +IMAGE_PATH = @srcdir@/img +OUTPUT_LANGUAGE = English +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = @srcdir@/head.html +HTML_FOOTER = @srcdir@/foot.html +HTML_STYLESHEET = @srcdir@/e.css +HTML_ALIGN_MEMBERS = YES +ENUM_VALUES_PER_LINE = 1 +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = YES +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = NO +SHOW_INCLUDE_FILES = NO +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 2 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = NO +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = @top_srcdir@/src/examples @top_srcdir@/src/bin +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 2 +IGNORE_PREFIX = emotion_ _emotion_ Emotion_ _Emotion_ EMOTION_ _EMOTION_ +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +GENERATE_MAN = YES +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = YES +GENERATE_XML = NO +XML_SCHEMA = +XML_DTD = +GENERATE_AUTOGEN_DEF = NO +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = NO +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = NO +COLLABORATION_GRAPH = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +SEARCHENGINE = NO diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..f5cdc41 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,33 @@ +MAINTAINERCLEANFILES = Makefile.in + +.PHONY: doc + +PACKAGE_DOCNAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc + +if EFL_BUILD_DOC + +doc-clean: + rm -rf html/ latex/ man/ xml/ $(top_builddir)/$(PACKAGE_DOCNAME).tar* + +doc: all doc-clean + $(efl_doxygen) + cp $(srcdir)/img/* html/ + cp $(srcdir)/img/* latex/ + rm -rf $(PACKAGE_DOCNAME).tar* + mkdir -p $(PACKAGE_DOCNAME)/doc + cp -R html/ latex/ man/ $(PACKAGE_DOCNAME)/doc + tar cf $(PACKAGE_DOCNAME).tar $(PACKAGE_DOCNAME)/ + bzip2 -9 $(PACKAGE_DOCNAME).tar + rm -rf $(PACKAGE_DOCNAME)/ + mv $(PACKAGE_DOCNAME).tar.bz2 $(top_builddir) + +clean-local: doc-clean + +else + +doc: + @echo "Documentation not built. Run ./configure --help" + +endif + +EXTRA_DIST = Doxyfile.in $(wildcard img/*.*) e.css head.html foot.html examples.dox diff --git a/doc/e.css b/doc/e.css index 604ee7f..2dd6b44 100644 --- a/doc/e.css +++ b/doc/e.css @@ -1,161 +1,273 @@ +/* + Author: + Andres Blanc + DaveMDS Andreoli + + Supported Browsers: + ie7, opera9, konqueror4 and firefox3 + + Please use a different file for ie6, ie5, etc. hacks. +*/ + + +/* Necessary to place the footer at the bottom of the page */ +html, body { + height: 100%; + margin: 0px; + padding: 0px; +} + +#container { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -53px; +} + +#footer, #push { + height: 53px; +} + + +* html #container { + height: 100%; +} + +/* Prevent floating elements overflowing containers */ +.clear { + clear: both; + width: 0px; + height: 0px; +} + +/* Flexible & centered layout from 750 to 960 pixels */ +.layout { + max-width: 960px; + min-width: 760px; + margin-left: auto; + margin-right: auto; +} + body { - 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%; } diff --git a/doc/examples.dox b/doc/examples.dox new file mode 100644 index 0000000..5e193f1 --- /dev/null +++ b/doc/examples.dox @@ -0,0 +1,104 @@ +/** + * @page Examples Examples + * + * Here is a page with some Emotion examples explained: + * + * @li @ref emotion_basic_example_c + * @li @ref emotion_signals_example.c "Emotion signals" + * @li @ref emotion_test_main.c "emotion_test - full API usage" + * + */ + +/** + * @page emotion_basic_example_c Emotion - Basic library usage + * + * This example shows how to setup a simple Emotion object, make it start + * playing and register a callback that tells when the playback started. See @ref + * emotion_basic_example.c "the full code here". + * + * @dontinclude emotion_basic_example.c + * + * We start this example by including some header files that will be necessary + * to work with Emotion, and to display some debug messages: + * + * @until stdio.h + * + * Then a callback will be declared, to be called when the object starts its + * playback: + * + * @until } + * + * Some basic setup of our canvas, window and background is necessary before + * displaying our object on it. This setup also includes reading the file to be + * opened from the program's argument list. Since this is not directly related + * to Emotion itself, we are just displaying the code for this without an + * explanation for it: + * + * @until evas_object_show(bg); + * + * Finally, we start the Emotion part. First we have to create the object in + * this canvas, and initialize it: + * + * @until emotion_object_init + * + * Notice that we didn't specify which module will be used, so emotion will use + * the first module found. There's no guarantee of the order that the modules + * will be found, so if you need to use one of them specifically, please be + * explicit in the second argument of the function emotion_object_init(). + * + * Now the callback can be registered to this object. It's a normal Evas smart + * object callback, so we add it with evas_object_smart_callback_add(): + * + * @until NULL + * + * The object itself is ready for use, but we need to load a file to it. This is + * done by the following function: + * + * @until file_set + * + * This object can play audio or video files. For the latter, the image must be + * displayed in our canvas, and that's why we need to add the object to the + * canvas. So, like any other Evas object in the canvas, we have to specify its + * position and size, and explicitly set its visibility. These are the position + * and dimension where the video will be displayed: + * + * @until evas_object_show + * + * Since the basic steps were done, we can now start playing our file. For this, + * we can just call the basic playback control function, and then we can go to + * the main loop and watch the audio/video playing: + * + * @until main_loop_begin + * + * The rest of the code doesn't contain anything special: + * + * @until } + * + * This code just free the canvas, shutdown the library, and has an entry point + * for exiting on error. + */ + + +/** + * @example emotion_basic_example.c + * This example show how to create and play an Emotion object. See @ref + * emotion_basic_example_c "the explanation here". + */ + +/** + * @example emotion_signals_example.c + * + * This example shows that some of the information available from the emotion + * object, like the media file play length, aspect ratio, etc. can be not + * available just after setting the file to the emotion object. + * + * One callback is declared for each of the following signals, and some of the + * info about the file is displayed. Also notice that the order that these + * signals are emitted can change depending on the module being used. Following + * is the full source code of this example: + */ + +/** + * @example emotion_test_main.c + * This example covers the entire emotion API. Use it as a reference. + */ diff --git a/doc/foot.html b/doc/foot.html index 0d3303d..d43cf8f 100644 --- a/doc/foot.html +++ b/doc/foot.html @@ -1,6 +1,18 @@ + +
+ + + + + + + -
-

Copyright © Enlightenment.org

-

$projectname Documentation Generated: $datetime

- + + + diff --git a/doc/head.html b/doc/head.html index c79a91d..16696c4 100644 --- a/doc/head.html +++ b/doc/head.html @@ -1,43 +1,68 @@ - - - - $title - - + + $title + + + + + + + + + + + - - - - - - -
- - - - - -
Download
-
- - - - - - - -
-
-
- - - - - -
Support
-
- -
+ +
+ + + +
+
diff --git a/doc/img/e.png b/doc/img/e.png new file mode 100644 index 0000000..d42aeb4 Binary files /dev/null and b/doc/img/e.png differ diff --git a/doc/img/edoxy.css b/doc/img/edoxy.css new file mode 100644 index 0000000..311ca23 --- /dev/null +++ b/doc/img/edoxy.css @@ -0,0 +1,486 @@ +/* + * This file contain a custom doxygen style to match e.org graphics + */ + + + +/* BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +}*/ +BODY, TD { + font-size: 12px; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { + font-weight: bold +} +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navpath { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { + text-decoration: none; + background-color: #6666cc; + color: #ffffff +} +A.el { + text-decoration: none; + font-weight: bold +} +A.elRef { + font-weight: bold +} +A.code:link { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.code:visited { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.codeRef:link { + font-weight: normal; + color: #0000FF +} +A.codeRef:visited { + font-weight: normal; + color: #0000FF +} +A:hover, A:visited:hover { + text-decoration: none; + /* background-color: #f2f2ff; */ + color: #000055; +} +A.anchor { + color: #000; +} +DL.el { + margin-left: -1cm +} +.fragment { + font-family: monospace, fixed; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { + margin-left: 16px; + font-style: italic; + font-size: 90% +} +/*BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +}*/ +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { + text-align: center; +} +IMG.formulaDsp { +} +IMG.formulaInl { + vertical-align: middle; +} +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +SPAN.vhdldigit { color: #ff00ff } +SPAN.vhdlchar { color: #000000 } +SPAN.vhdlkeyword { color: #700070 } +SPAN.vhdllogic { color: #ff0000 } + +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { + color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { + font-size: 75%; +} +a { + color: #1A41A8; +} +a:visited { + color: #2A3798; +} +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { + background: #e8eef2; + font-weight: bold; +} +HR { + height: 1px; + border: none; + border-top: 1px solid black; +} + +/* Style for detailed member documentation */ +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; + margin-left: 3px; +} +.memnav { + background-color: #eeeeee; + border: 1px solid #dddddd; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +.memitem { + padding: 4px; + background-color: #eeeeee; + border-width: 1px; + border-style: solid; + border-color: #dddddd; + -moz-border-radius: 4px 4px 4px 4px; +} +.memname { + white-space: nowrap; + font-weight: bold; + color: #ffffff; +} +.memdoc{ + padding-left: 10px; +} +.memproto { + background-color: #111111; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #000000; + font-weight: bold; + -moz-border-radius: 4px 4px 4px 4px; +} +.paramkey { + text-align: right; + color: #ffffff; +} +.paramtype { + white-space: nowrap; + color: #aaaaaa; +} +.paramname { + color: #ff0000; + font-style: italic; + white-space: nowrap; +} +/* End Styling for detailed member documentation */ + +/* for the tree view */ +.ftvtree { + font-family: sans-serif; + margin:0.5em; +} +/* these are for tree view when used as main index */ +.directory { + font-size: 9pt; + font-weight: bold; +} +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* The following two styles can be used to replace the root node title */ +/* with an image of your choice. Simply uncomment the next two styles, */ +/* specify the name of your image and be sure to set 'height' to the */ +/* proper pixel height of your image. */ + +/* .directory h3.swap { */ +/* height: 61px; */ +/* background-repeat: no-repeat; */ +/* background-image: url("yourimage.gif"); */ +/* } */ +/* .directory h3.swap span { */ +/* display: none; */ +/* } */ + +.directory > h3 { + margin-top: 0; +} +.directory p { + margin: 0px; + white-space: nowrap; +} +.directory div { + display: none; + margin: 0px; +} +.directory img { + vertical-align: -30%; +} +/* these are for tree view when not used as main index */ +.directory-alt { + font-size: 100%; + font-weight: bold; +} +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} +.directory-alt > h3 { + margin-top: 0; +} +.directory-alt p { + margin: 0px; + white-space: nowrap; +} +.directory-alt div { + display: none; + margin: 0px; +} +.directory-alt img { + vertical-align: -30%; +} + diff --git a/doc/img/emotion_ratio.eps b/doc/img/emotion_ratio.eps new file mode 100644 index 0000000..624196b --- /dev/null +++ b/doc/img/emotion_ratio.eps @@ -0,0 +1,4541 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: (ImageMagick) +%%Title: (bla.eps) +%%CreationDate: (2011-08-04T18:14:47-03:00) +%%BoundingBox: -0 -0 566 174 +%%HiResBoundingBox: 0 0 565.663 174 +%%DocumentData: Clean7Bit +%%LanguageLevel: 1 +%%Pages: 1 +%%EndComments + +%%BeginDefaults +%%EndDefaults + +%%BeginProlog +% +% Display a color image. The image is displayed in color on +% Postscript viewers or printers that support color, otherwise +% it is displayed as grayscale. +% +/DirectClassPacket +{ + % + % Get a DirectClass packet. + % + % Parameters: + % red. + % green. + % blue. + % length: number of pixels minus one of this color (optional). + % + currentfile color_packet readhexstring pop pop + compression 0 eq + { + /number_pixels 3 def + } + { + currentfile byte readhexstring pop 0 get + /number_pixels exch 1 add 3 mul def + } ifelse + 0 3 number_pixels 1 sub + { + pixels exch color_packet putinterval + } for + pixels 0 number_pixels getinterval +} bind def + +/DirectClassImage +{ + % + % Display a DirectClass image. + % + systemdict /colorimage known + { + columns rows 8 + [ + columns 0 0 + rows neg 0 rows + ] + { DirectClassPacket } false 3 colorimage + } + { + % + % No colorimage operator; convert to grayscale. + % + columns rows 8 + [ + columns 0 0 + rows neg 0 rows + ] + { GrayDirectClassPacket } image + } ifelse +} bind def + +/GrayDirectClassPacket +{ + % + % Get a DirectClass packet; convert to grayscale. + % + % Parameters: + % red + % green + % blue + % length: number of pixels minus one of this color (optional). + % + currentfile color_packet readhexstring pop pop + color_packet 0 get 0.299 mul + color_packet 1 get 0.587 mul add + color_packet 2 get 0.114 mul add + cvi + /gray_packet exch def + compression 0 eq + { + /number_pixels 1 def + } + { + currentfile byte readhexstring pop 0 get + /number_pixels exch 1 add def + } ifelse + 0 1 number_pixels 1 sub + { + pixels exch gray_packet put + } for + pixels 0 number_pixels getinterval +} bind def + +/GrayPseudoClassPacket +{ + % + % Get a PseudoClass packet; convert to grayscale. + % + % Parameters: + % index: index into the colormap. + % length: number of pixels minus one of this color (optional). + % + currentfile byte readhexstring pop 0 get + /offset exch 3 mul def + /color_packet colormap offset 3 getinterval def + color_packet 0 get 0.299 mul + color_packet 1 get 0.587 mul add + color_packet 2 get 0.114 mul add + cvi + /gray_packet exch def + compression 0 eq + { + /number_pixels 1 def + } + { + currentfile byte readhexstring pop 0 get + /number_pixels exch 1 add def + } ifelse + 0 1 number_pixels 1 sub + { + pixels exch gray_packet put + } for + pixels 0 number_pixels getinterval +} bind def + +/PseudoClassPacket +{ + % + % Get a PseudoClass packet. + % + % Parameters: + % index: index into the colormap. + % length: number of pixels minus one of this color (optional). + % + currentfile byte readhexstring pop 0 get + /offset exch 3 mul def + /color_packet colormap offset 3 getinterval def + compression 0 eq + { + /number_pixels 3 def + } + { + currentfile byte readhexstring pop 0 get + /number_pixels exch 1 add 3 mul def + } ifelse + 0 3 number_pixels 1 sub + { + pixels exch color_packet putinterval + } for + pixels 0 number_pixels getinterval +} bind def + +/PseudoClassImage +{ + % + % Display a PseudoClass image. + % + % Parameters: + % class: 0-PseudoClass or 1-Grayscale. + % + currentfile buffer readline pop + token pop /class exch def pop + class 0 gt + { + currentfile buffer readline pop + token pop /depth exch def pop + /grays columns 8 add depth sub depth mul 8 idiv string def + columns rows depth + [ + columns 0 0 + rows neg 0 rows + ] + { currentfile grays readhexstring pop } image + } + { + % + % Parameters: + % colors: number of colors in the colormap. + % colormap: red, green, blue color packets. + % + currentfile buffer readline pop + token pop /colors exch def pop + /colors colors 3 mul def + /colormap colors string def + currentfile colormap readhexstring pop pop + systemdict /colorimage known + { + columns rows 8 + [ + columns 0 0 + rows neg 0 rows + ] + { PseudoClassPacket } false 3 colorimage + } + { + % + % No colorimage operator; convert to grayscale. + % + columns rows 8 + [ + columns 0 0 + rows neg 0 rows + ] + { GrayPseudoClassPacket } image + } ifelse + } ifelse +} bind def + +/DisplayImage +{ + % + % Display a DirectClass or PseudoClass image. + % + % Parameters: + % x & y translation. + % x & y scale. + % label pointsize. + % image label. + % image columns & rows. + % class: 0-DirectClass or 1-PseudoClass. + % compression: 0-none or 1-RunlengthEncoded. + % hex color packets. + % + gsave + /buffer 512 string def + /byte 1 string def + /color_packet 3 string def + /pixels 768 string def + + currentfile buffer readline pop + token pop /x exch def + token pop /y exch def pop + x y translate + currentfile buffer readline pop + token pop /x exch def + token pop /y exch def pop + currentfile buffer readline pop + token pop /pointsize exch def pop + /Times-Roman findfont pointsize scalefont setfont + x y scale + currentfile buffer readline pop + token pop /columns exch def + token pop /rows exch def pop + currentfile buffer readline pop + token pop /class exch def pop + currentfile buffer readline pop + token pop /compression exch def pop + class 0 gt { PseudoClassImage } { DirectClassImage } ifelse +} bind def +%%EndProlog +%%Page: 1 1 +%%PageBoundingBox: 0 0 566 174 +userdict begin +DisplayImage +0 0 +565.663 173.619 +12 +707 217 +1 +1 +1 +8 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFF +FFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF0000000000 +00000000FFFFFFFFFFFF0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000FFFFFFFFFF +000000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF00000000000000 +00FFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF00060B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B05FFFFFFFFFFFFFFFFFFFF00 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFF +FFFFFFFF0000000000000000FFFFFFFFFFFF000000000000000000FFFFFFFFFFFF000000 +0000081B607F7F7F7F7F7F471B1B1B1B1B1B4A7F7F7F7F7F7F5D1B1B1B1B1B1B317F7F7F +7F7F7F731B1B1B1B1B1B1B7F7F7F7F7F7F7F251B1B1B1B1B1B6A7F7F7F7F7F7F3E1B1B1B +1B1B1B547F7F7F7F7F7F541B1B1B1B1B1B3E7F7F7F7F7F7F6A1B1B1B1B1B1B257F7F7F7F +7F7F7F1B1B1B1B1B1B1B737F7F7F7F7F7F341B1B1B1B1B1B5D7F7F7F7F7F7F4A1B1B1B1B +1B1B477F7F7F7F7F7F601B1B1B1B1B1B210AFFFFFFFFFF000000000000000000FFFFFFFF +FFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF000000000000 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0005868686 +868686868686868686868686868686868686868686868686868686868686868686868686 +868686868686868686868686868686868686868686868686868686868686868686868686 +868686868686868686868686868686868686868686868686868686868686868686868686 +868686868686868686868686868686868686868686868686868686868686868686868686 +868686868686868686868600FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +3ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFF +FFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFF +FFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFF +FF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFF +FFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC92 +10FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFF +FFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFF +FFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF0000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +3ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC07 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFF +FFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFF +FFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3AA988673788B9EB0CACCCCCCCC9210FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBC9EA6C3CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFF +FF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC763939393939A7CCCC +CCCCCC773939393939CACCCCCCCCCCCCCCCCCCCC57393939393939393939393A424E5964 +6F81A6C9CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A39393939393939 +393939393939393939393939393939393939ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCAE71350400000000000000000E4884BECC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC845F5F86CCCCCCCC +CCCCCCCCCCCCCCCCCCCC825F5F8CCCCCCC675F5FB4CCCCCCCCCC975F5F5F5F5F606A7E92 +B8CCCCCCCCCCCCCCCCCCCCCCCCCCCC6F5F5F5F5F5F5F5F5F5F5F5F5F5F6BCCCCCCCCCCCC +CCCCCCCCCA7E1900000001309DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCA140000000012C9CCCCCCCCCC560000000000CACCCCCC +CCCCCCCCCCCCCC2A000000000000000000000000000000000000062A5287C7CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC000000000000000000000000000000000000000000 +00000000009FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA737000000000000000000000000 +000000055C8A10FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000027CCCCCCCCCCCCCCCCCCCCCCCCCCCC1F0000 +74CCCCCC0E00009ECCCCCCCCCC6800000000000000000002337AC7CCCCCCCCCCCCCCCCCC +CCCC1E0000000000000000000000000015CCCCCCCCCCCCCCCCCCBD2A0000000000000000 +56CBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9000000000005ECCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000000 +0000000000000000000000000000000000105CADCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00000000000000000000000000000000000000000000000000009FCCCCCCCCCCCCCC +CCCCCCCCCCCCCCB94E020000000000000000000000000000000000000B09FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC92000003C5CCCCCCCCCCCCCCCCCCCCCCCCBF010000A0CCCCCC0E00009ECCCCCCCCCC +6800000000000000000000000026A8CCCCCCCCCCCCCCCCCCCC1E00000000000000000000 +00000015CCCCCCCCCCCCCCCCBC250000000000000000000050CBCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC430000000000ABCCCCCCCCCCCC +560000000000CACCCCCCCCCCCCCCCCCCCC2A000000000000000000000000000000000000 +0000000000000043BBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0000000000000000000000 +0000000000000000000000000000009FCCCCCCCCCCCCCCCCCCCCCCCCCCAA160000000000 +0000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBD0000009ECCCCCCCCCCCC +CCCCCCCCCCCC95000005C6CCCCCC0E00009ECCCCCCCCCC68000000000000000000000000 +00058CCCCCCCCCCCCCCCCCCC1E0000000000000000000000000015CCCCCCCCCCCCCCCC3A +00000000000000000000000073CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCBD05000000002DCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCC +CCCCCCCC2A0000000003121212121212120900000000000000000000000000128CCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC000000000000000000000000000000000000000000000000 +00009FCCCCCCCCCCCCCCCCCCCCCCCC9D0E000000000000001E628A9EB2AC98824D0E0000 +00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC1D000072CCCCCCCCCCCCCCCCCCCCCCCC6A00002ACCCCCC +CC0E00009ECCCCCCCCCC6800000000000000000000000000000AA8CCCCCCCCCCCCCCCC1E +0000000000000000000000000015CCCCCCCCCCCCCC86000000001061867D4E030000000A +B6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFF +FFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC75000000 +00007ACCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCC +CCCCCCCCCCCABFB28A5E310400000000000000005ACCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +0000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9B0700000000000032A5CCCCCCCCCCCCCCCCCCC9861300000000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +49000047CCCCCCCCCCCCCCCCCCCCCCCC3E000056CCCCCCCC0E00009ECCCCCCCCCC680000 +40BFBFBFBDA88F4E09000000001AC5CCCCCCCCCCCCCC1E000074A6A6A6A6A6A6A6A6A6A6 +AACCCCCCCCCCCCC4130000003EBFCCCCCCCCAA1900000046CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC280000000008C1CCCCCCCCCCCCCC560000 +000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCB866 +13000000000000006FCCCCCCCCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBE160000000000067CCBCCCCCC +CCCCCCCCCCCCCCCCCCBF4A000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7500001CCCCCCCCCCCCCCCCCCC +CCCCCC13000082CCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCBD3C000000 +0074CCCCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7D0000002EC6 +CCCCCCCCCCCCAB0E000002B6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003DCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCA700000000004ACCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCC +CC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC75C0000000000000189CCCCCC +CCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC4100000000000693CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB5200 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCA1000000BDCCCCCCCCCCCCCCCCCCCCB4000000AECCCCCCCC0E00 +009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCB5300000016C7CCCCCCCCCCCC1E00008E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC29000003ADCCCCCCCCCCCCCCCC7600000067CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFF +FFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF002ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC5A000000000098CC +CCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC8E0B000000000008B8CCCCCCCCCCCCCCCCCCCCCC00000000 +0052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7E000000 +00000290CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB3400FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC70500 +0092CCCCCCCCCCCCCCCCCCCC8900000ECBCCCCCCCC0E00009ECCCCCCCCCC68000044CCCC +CCCCCCCCCCCCCCC72A00000084CCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCA200000052CCCCCCCCCCCCCCCCCCC81D000017CBCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8E595974CCCCCCCCCCCCCCCCCCCC +CCCCCCCC80595985CCCCCC6A5959AACCCCCCCCCC9D5959595959595E687286ADCACCCCCC +CCCCCCCCCCCCCCCCCC72595959595959595959595959595DCCCCCCCCCCCCCCCCCCCCB170 +361B080A1E3D78B9CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0013CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCC811000000001ACBCCCCCCCCCCCCCCCC560000000000 +CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +8F01000000000059CCCCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA1D000000000056CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC8B02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC2B000067CCCCCCCCCCCCCCCCCCCC5E +000039CCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCC9E00000048 +CCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000000ABCCCCCCCCCC +CCCCCCCCCC6F000000A6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9A000004BBCCCCCCCCCCCCCCCCCCCCCCCCC60E00008ACCCCCC1D00 +008FCCCCCCCCCC7700000000000000000000000A4899CCCCCCCCCCCCCCCCCCCC2D000000 +0000000000000000000006CCCCCCCCCCCCCCCCB950020000000000000000065FC2CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0001BACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC8C000000000067CCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A00 +00000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000000000006B8CCCCCCCC +CCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC8C000000000016C2CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC920BFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC5700003CCCCCCCCCCCCCCCCCCCCC32000064CCCCCCCCCC0E00009ECC +CCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCC2A000010CACCCCCCCCCC1E00008ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC3300002ACCCCCCCCCCCCCCCCCCCCCCB602000074CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFF +FFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1D0000 +72CCCCCCCCCCCCCCCCCCCCCCCC88000010C8CCCCCC1D00008FCCCCCCCCCC770000000000 +00000000000000000030AFCCCCCCCCCCCCCCCC2D0000000000000000000000000006CCCC +CCCCCCCCCCAC17000000093B514E360500000026B9CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF000070CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3E0000000002B4CCCCCCCCCC +CCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCA1A00000000005BCCCCCCCCCCCCCCCCCCCC000000000052CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3200000000007ACC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC83000011CC +CCCCCCCCCCCCCCCCCA09000090CCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCC +CCCCCCCCCCCC78000000A2CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6 +0600006DCCCCCCCCCCCCCCCCCCCCCCCC2D000042CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6A000026CCCCCCCCCCCCCCCCCCCCCCCC +3B00005ACCCCCCCC1D00008FCCCCCCCCCC77000033C6C6C6C5BBAF8E61170000000897CC +CCCCCCCCCCCC2D000073B9B9B9B9B9B9B9B9B9B9BACCCCCCCCCCCCB21000000B73C4CCCC +CCCCBE620500001EC1CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000023CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCBA030000000037CCCCCCCCCCCCCCCCCCCC560000000000CACCCC +CCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC75 +00000000001ACCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCB0000000000008C1CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAF000000B2CCCCCCCCCCCCCCCCA8000000BB +CCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCAE0000007ACCCC +CCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9E0000009ACCCCCCCCCCCCCCCCCC +CCCCCC5A000012CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCB6020000A6CCCCCCCCCCCCCCCCCCCCB7020000A7CCCCCCCC1D00008FCC +CCCCCCCC77000035CCCCCCCCCCCCCCCCCA7C0800000DACCCCCCCCCCCCC2D00007FCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCC82C000011AACCCCCCCCCCCCCCCC9707000048CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000A3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC710000 +00000085CCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A00000000 +29CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC30D0000000000B5CCCCCCCCCCCC +CCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC8000000000004BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC0F000087CCCCCCCCCCCCCCCC7D00001ACCCCCCCCCCCC0E00009ECCCCCCCC +CC68000044CCCCCCCCCCCCCCCCCCCCCCCC1600005DCCCCCCCCCC1E00008ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC81000002C4CCCCCCCCCCCCCCCCCCCCCCCC86000000C2CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A000059CC +CCCCCCCCCCCCCCCCCC6D000029CCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCC +CCCCCCCCCCA206000039CCCCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +770000019ACCCCCCCCCCCCCCCCCCCC7E0000009ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF00000056CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC23000000000DC6CCCCCCCCCCCCCCCCCC +CC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC3F000000000082CCCCCCCCCCCCCCCCCC000000000052CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC51000000000089CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A00005CCCCCCC +CCCCCCCCCC52000046CCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCC +CCCCCCCC3C000041CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000020 +CCCCCCCCCCCCCCCCCCCCCCCCCCAB000000A6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC88000010C8CCCCCCCCCCCCCCCCCC20000076 +CCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCC76000000A2CCCC +CCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB1E00004ECCCCCCCCCCCCCCCCCC +CCCCCB2C00003FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000EC7CCCCCCCCCCCCCC +CCCCCCCCCCCCA2000000000055CCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCC +CCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6D0000 +0000004FCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC220000000000B2CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC66000031CCCCCCCCCCCCCCCC26000072CCCCCCCC +CCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC55000024CCCCCCCCCC +1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4A000037CCCCCCCCCCCCCCCCCCCCCCCCCC +C30000008BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCC70F00008BCCCCCCCCCCCCCCCC9F000006BECCCCCCCCCC1D00008FCCCCCCCC +CC77000035CCCCCCCCCCCCCCCCCCCCCCC71400005BCCCCCCCCCC2D00007FCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9E000000A4CCCCCCCCCCCCCCCCCCCCCCCC81000002BECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000000089CCCCCCCCCCCCCCCCCCCCCCCCCC550000000000A2 +CCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9B00000000002ECCCCCCCCCCCCCCCCCC +000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC30100 +0000000ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC92000008CACCCCCCCCCCCCC40300009ECCCCCCCCCCCC0E00009ECCCCCCCCCC6800 +0044CCCCCCCCCCCCCCCCCCCCCCCC6E00000ECCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC3000004ECCCCCCCCCCCCCCCCCCCCCCCCCCCC0E000071CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC5800003ECCCCCC +CCCCCCCCCC52000046CCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCC +CCCCCCCC54000028CCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6C000018 +CCCCCCCCCCCCCCCCCCCCCCCCCCC10100008FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +00003CCCCCCCCCCCCCCCCCCCCCCCCCC60E0000000024CCCCCCCCCCCCCCCCCCCCCCCC5600 +00000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCBB000000000021CCCCCCCCCCCCCCCCCC00000000001739393939393939 +39393939393939393939393995CCCCCCCCCCCCCCB200000000002FCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBE000000A7CCCCCCCCCC +CC9C000004C6CCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCC +CC82000006CCCCCCCCCC1E00004766666666666666666666A4CCCCCCCC26000064CCCCCC +CCCCCCCCCCCCCCCCCCCCCC23000066CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA6000003BACCCCCCCCCCCCC50C000094CCCCCCCC +CCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCCCC80000002CACCCCCCCC +2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC40000042CCCCCCCCCCCCCCCCCCCCCCCCCC +CC1F000062CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000002B9CCCCCCCCCCCCCCCCCC +CCCC87000000000072CCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCC +CCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC90000000000 +12CCCCCCCCCCCCCCCCCC000000000000000000000000000000000000000000000000007F +CCCCCCCCCCCCCCA300000000003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC1D00007CCCCCCCCCCCCC71000029CCCCCCCCCCCCCC0E +00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC8B000000CBCCCCCCCC1E0000 +00000000000000000000007BCCCCCCCC1F00006DCCCCCCCCCCCCCCCCCCCCCCCCCCCC2C00 +005ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC28000072CCCCCCCCCCCC84000017CACCCCCCCCCCCC1D00008FCCCCCCCCCC7700 +0035CCCCCCCCCCCCCCCCCCCCCCCC9A000000BECCCCCCCC2D000000000000000000000000 +006CCCCCCCCC2F00005DCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A00004FCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF00000000006ECCCCCCCCCCCCCCCCCCCCCC3A0000000004BBCCCCCCCC +CCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0A0000000004CCCCCCCCCCCCCCCCCC000000 +000000000000000000000000000000000000000000007FCCCCCCCCCCCCCC940000000000 +4ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC49000051CCCCCCCCCCCC46000055CCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CC +CCCCCCCCCCCCCCCCCCCCCC94000000C4CCCCCCCC1E000000000000000000000000007BCC +CCCCCC18000074CCCCCCCCCCCCCCCCCCCCCCCCCCCC33000055CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC76000024CCCCCCCCCC +CC37000063CCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCC +CCA9000000B0CCCCCCCC2D000000000000000000000000006CCCCCCCCC2200006ACCCCCC +CCCCCCCCCCCCCCCCCCCCCC46000041CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000 +22CCCCCCCCCCCCCCCCCCCCB6020000000042CCCCCCCCCCCCCCCCCCCCCCCCCC5600000000 +00CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC160000000000C2CCCCCCCCCCCCCCCC00000000000000000000000000000000 +0000000000000000007FCCCCCCCCCCCCCC85000000000056CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC75000026CCCCCCCCCCCC1A00 +0080CCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC9C00 +0000BDCCCCCCCC1E000000000000000000000000007BCCCCCCCC1200007ACCCCCCCCCCCC +CCCCCCCCCCCCCCCC3A00004DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCBE060000A4CCCCCCCCB5020001B0CCCCCCCCCCCCCC1D +00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCCCCAA000000AECCCCCCCC2D0000 +2B464646464646464646468ECCCCCCCC2000006CCCCCCCCCCCCCCCCCCCCCCCCCCCCC4A00 +003DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000A2CCCCCCCCCCCCCCCCCC6C00 +000000008FCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A +0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC160000000000C4CC +CCCCCCCCCCCCCC000000000000000000000000000000000000000000000000007FCCCCCC +CCCCCCCC83000000000056CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCA1000002C4CCCCCCCCBB000000ACCCCCCCCCCCCCCC0E00009E +CCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC9E000000BACCCCCCCC1E0000000000 +00000000000000007BCCCCCCCC0E00007ECCCCCCCCCCCCCCCCCCCCCCCCCCCC3D000049CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC46000057CCCCCCCC69000032CCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CC +CCCCCCCCCCCCCCCCCCCCCC9C000000BCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC2C000060CCCCCCCCCCCCCCCCCCCCCCCCCCCC3E00004CCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF00000000000054CCCCCCCCCCCCCCCCCC1F0000000014CACCCCCCCCCCCCCCCC +CCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC090000000007CCCCCCCCCCCCCCCCCC000000000052 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9200000000004ACCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC706 +00009CCCCCCCCC9000000CCBCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCC +CCCCCCCCCCCCCCCC97000000C2CCCCCCCC1E00006F9F9F9F9F9F9F9F9F9F9FBACCCCCCCC +14000078CCCCCCCCCCCCCCCCCCCCCCCCCCCC36000051CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9400000FC7CCCCCC1D0000 +80CCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCCCC8500 +0001C9CCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A00004ACCCCCCCCCCCC +CCCCCCCCCCCCCCCC2700005CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000E000000000EC6 +CCCCCCCCCCCCCC9E00000000005ECCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACC +CCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCC8000000000016CCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCA200000000003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC2C000071CCCCCCCC65000036CCCC +CCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC8E000000C9 +CCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1B000071CCCCCCCCCCCCCCCCCC +CCCCCCCCCC30000059CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCA1700008ACCCC9B00000AC3CCCCCCCCCCCCCCCC1D00008F +CCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCCCC5A000022CCCCCCCCCC2D00007FCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC60000022CCCCCCCCCCCCCCCCCCCCCCCCCCC704000084CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0026000000000087CCCCCCCCCCCCCC510000000000 +ADCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A000000 +0029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBB000000000026CCCCCCCCCC +CCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCB1000000000032CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC58000046CCCCCCCC3A000062CCCCCCCCCCCCCCCC0E00009ECCCCCC +CCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC86000004CCCCCCCCCC1E00008ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC2200006ACCCCCCCCCCCCCCCCCCCCCCCCCCCC29000061CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +6300003DCCCC4E00004FCCCCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCC +CCCCCCCCCCCCCCCA1E000054CCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +91000001B3CCCCCCCCCCCCCCCCCCCCCCCC92000000B6CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003B09000000003ACCCCCCCCCCCCC50B000000002ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC9A000000000035CCCCCCCCCCCCCCCCCC000000000052CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1000000000012CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8400001A +CCCCCCCC0E00008ECCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCC +CCCCCCCCCC7700000BCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC290000 +5ACCCCCCCCCCCCCCCCCCCCCCCCCCCC1A00006ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB1010003BAC30A00009DCCCCCC +CCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCCCCCCCCCC8900000093CC +CCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC40E000063CCCCCCCCCCCCCCCC +CCCCCCCC4100002BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E4C0000000002B7CCCC +CCCCCC8200000000007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCC +CCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6C00 +0000000057CCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC1B0000000000B6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB0000000BCCCCCAF000000BACCCCCCCCCC +CCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCCC5F00001ACCCCCCCC +CC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3B000043CCCCCCCCCCCCCCCCCCCCCCCC +CCCA0400007DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC330000708000001ECCCCCCCCCCCCCCCCCCCC1D00008FCCCCCC +CCCC77000035CCCCCCCCCCCCCCCCCCCCB61200002ACCCCCCCCCCCC2D00007FCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC60000008B1CCCCCCCCCCCCCCCCCCCC9A00000086CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF003E9A00000000006DCCCCCCCCCC360000000008C2CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3F00000000008ACCCCCCCCCCCCCCCC +CC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4A +00000000008DCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC0F000091CCCC84000019CCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68 +000044CCCCCCCCCCCCCCCCCCCCCCCC46000036CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC5700002CCCCCCCCCCCCCCCCCCCCCCCCCCCB800000098CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8200 +00233300006CCCCCCCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCCC +CCCCA1190000049BCCCCCCCCCCCC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBB14 +000026BECCCCCCCCCCCCCCCCB11600002BC9CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +3ECC1D0000000020CCCCCCCCB301000000004CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC56 +0000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCC40D0000000000BBCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7A000000000053CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3A000066CCCC +59000045CCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCC +CCCC2A000052CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7200000FCCCC +CCCCCCCCCCCCCCCCCCCCCC9B000000B4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC40B0000000002B7CCCCCCCCCCCCCC +CCCCCC1D00008FCCCCCCCCCC77000035CCCCCCCCCCCCB4873B0100000081CCCCCCCCCCCC +CC2D00007FCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC970200001F9DCCCCCCCCCCCC8D14 +000009AECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC07 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC6A00000000009FCCCCCC67 +00000000009ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCC +CCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC760000000000 +22CCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCAA00000000000CC5CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6600003ACCCC2D000071CCCCCCCCCCCCCCCCCC +0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCCC20300006ECCCCCCCCCC1E00 +008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8E000000B1CCCCCCCCCCCCCCCCCCCCCCCC7000 +0005CACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFF +FFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC51000000003BCCCCCCCCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC77 +0000081F1F1F1E150900000000001795CCCCCCCCCCCCCCCC2D00000B1212121212121212 +1212129ECCCCCCCCCCCC8A060000002B627B795E220000000F9ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF003ECCB6020000000052CCCCCB1B000000001CCBCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA1D000000000061CCCCCCCCCCCCCCCCCCCC0000 +00000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC260000 +00000082CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC92000010CCC80600009CCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044 +CCCCCCCCCCCCCCCCCCCCCC900000008ECCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCB200000085CCCCCCCCCCCCCCCCCCCCCCCC44000028CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9F000000 +008ACCCCCCCCCCCCCCCCCCCCCC1D00008FCCCCCCCCCC7700000000000000000000000027 +76C2CCCCCCCCCCCCCCCCCC2D000000000000000000000000000099CCCCCCCCCCCCCCA128 +0000000000000000000036AECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC +3A000000000DC6CC9A000000000069CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC56000000 +0000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC6A000000000008BBCCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8100000000001EC6CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC920CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBE000000B1A3000003 +C5CCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCCC5100 +0003C0CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1800004ECCCCCCCC +CCCCCCCCCCCCCCCA1200005ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC45323239C7CCCCCCCCCCCCCCCCCCCCCC +4932329ECCCCCCCCCC8D323232323232384551668DB5CCCCCCCCCCCCCCCCCCCCCCCC5532 +32323232323232323232323232A6CCCCCCCCCCCCCCCCCB87430A00000000104B94CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC88000000000086CC4C00000000 +02B5CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC +2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC940200000000005BCCCCCC +CCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCC714000000000062CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8E02 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC1E00008678000027CCCCCCCCCCCCCCCCCCCC0E0000 +9ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCCCCBE0800002FCCCCCCCCCCCC1E00008ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4B00000CC6CCCCCCCCCCCCCCCCCCCC940000008CCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFF +FFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCBBEAEAFC0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF003ECCCCC70F0000000038C2090000000039CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC940E000000000008B9CCCCCCCCCCCCCCCCCCCCCC0000000000 +52CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7000000000 +00049ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3E00FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC4A00005A4D000052CCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCC +CCCCCCCCCCCCCC6600000069CCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC7E00000086CCCCCCCCCCCCCCCCCCCC4A000002BECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC5800 +0000000267000000000086CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CA +CCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9620100 +000000000189CCCCCCCCCCCCCCCCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCA3100000000000BA1CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC630000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7600002F2100007ECCCCCC +CCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCCCCCCCC9C03000002B0CC +CCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC008000022CACCCCCCCCCC +CCCCCCAE0300003BCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCA6000000000002000000000EC6CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000 +000029CCCCCCCCCCCCCCCCCCCCCCCCCCCCBC6C180000000000000070CCCCCCCCCCCCCCCC +CCCCCCCCCC000000000052CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCB40E00000000000D8FCCCCCCCCCCCCCCCCCCCCCCCCCCC65D000000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCA2000006010000AACCCCCCCCCCCCCCCCCCCC0E00009ECCCC +CCCCCC68000044CCCCCCCCCCCCCCCC98120000004ACCCCCCCCCCCCCC1E00008ECCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC5000000078CCCCCCCCCCCCCCCC3E0000008ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFF +FF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF003ECCCCCCCC2800000000000000000056CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000029CCCCCCCCCCCCCCCCCCC6 +B89164370600000000000000005ACCCCCCCCCCCCCCCCCCCCCCCCCCCC000000000052CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8A0200000000 +000044B6CCCCCCCCCCCCCCCCCCCC991F00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7 +06000000000BCACCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000044CCCCCCCCCCCC +AA580200000002ADCCCCCCCCCCCCCC1E00008ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +A50000000596CCCCCCCCCCCC6100000016CACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCC76000000 +000000000000A4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCC +CCCCCCCCCCCCCC2A0000000005191919191919180F040000000000000000000000000F88 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC000000000002060606060606060606060606060606 +06060606063ECCCCCCCCCCCCCCCCCCCCCCCC89060000000000000232759EB2C5BFAB9660 +1E000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC2C0000000035CCCCCCCCCCCCCC +CCCCCCCC0E00009ECCCCCCCCCC6800001A4C4C4C4A351C0000000000006BCCCCCCCCCCCC +CCCC1E0000283939393939393939393939B2CCCCCCCCCCCC43000000086DC7CCCCB94900 +0000007ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCBE060000000000000026CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCCCCCCCCCC2A0000000000 +00000000000000000000000000000000000000003BB8CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC000000000000000000000000000000000000000000000000000039CCCCCCCCCCCCCC +CCCCCCCCCCCC990C00000000000000000000000000000000000000000000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC580000000061CCCCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC +68000000000000000000000000000048CCCCCCCCCCCCCCCCCC1E00000000000000000000 +00000000A8CCCCCCCCCCCCB70B0000000006261D020000000031CBCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +003ECCCCCCCCCC460000000000000073CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +560000000000CACCCCCCCCCCCCCCCCCCCC2A000000000000000000000000000000000000 +000000000C54A4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0000000000000000000000 +00000000000000000000000000000039CCCCCCCCCCCCCCCCCCCCCCCCCCCCAA3600000000 +0000000000000000000000000000000407FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC840000 +00008DCCCCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC68000000000000000000000000 +0055C6CCCCCCCCCCCCCCCCCC1E0000000000000000000000000000A8CCCCCCCCCCCCCC7E +00000000000000000000000CABCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCC940000000000 +0005BDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC560000000000CACCCCCCCCCCCC +CCCCCCCC2A00000000000000000000000000000000000003254C83C5CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC000000000000000000000000000000000000000000000000 +000039CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9325000000000000000000000000000000 +01478010FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB000000000B8CCCCCCCCCCCCCCCCCCCC +CC0E00009ECCCCCCCCCC6800000000000000000000001B90CCCCCCCCCCCCCCCCCCCCCC1E +0000000000000000000000000000A8CCCCCCCCCCCCCCCC750000000000000000000EA2CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFF +FFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCA3E32323232325ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC733232323232CACCCCCCCCCCCCCCCCCCCC523232323232323232 +3232333B47525E6A7BA2C6CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC33 +323232323232323232323232323232323232323232323232325ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCA9A5E22000000000000000000043571AECC9210FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC10000017CCCCCCCCCCCCCCCCCCCCCCCC0E00009ECCCCCCCCCC680000 +000000000A1E325AA0CCCCCCCCCCCCCCCCCCCCCCCCCC1E00000000000000000000000000 +00A8CCCCCCCCCCCCCCCCCC871900000000000032A8CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB497 +85726065788A9DC1CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC7 +7E53323B5C96CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC92 +10FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFF +FFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFF +FFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC0700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF00CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0700FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00C6C6 +C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +C6C6C6C6C6C6C6C6C6C6C6C60700FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +3ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF01030303030303030303030303030303 +030303030303030303030303030303030303030303030303030303030303030303030303 +030303030303030303030303030303030303030303030303030303030303030303030303 +030303030303030303030303030303030303030303030303030303030303030303030303 +030303030303030303030303030303030303030303030303030303030303030303030301 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFF +FFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFF +FFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFF +FF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFF +FFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC92 +10FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFF +FFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFF +FFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007 +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FF +FFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003E +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFF +FFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFF +FFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +07CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF003ECCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCC00FFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003ECCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCC9210FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0007CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC00 +FFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000 +FFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFF00 +00000000000000FFFFFFFFFF001715151515151533757575757575631515151515151F75 +757575757575191515151515156A7575757575752E151515151515517575757575754315 +15151515153D75757575757557151515151515287575757575756F151515151515157275 +7575757575251515151515155D75757575757539151515151515467575757575754E1515 +1515151530757575757575671515151515151B757575757575751B0F010000000000FFFF +FFFFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF00000000 +00000000FFFFFFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF0006ACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +ACACACACACACACACACACACACACACACACACACACACACAC00FFFFFFFFFFFFFFFFFFFF000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFF00000000000000 +00FFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFF00 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000FFFFFFFFFFFF0000000000000000FF +FFFFFFFFFF0000000000000000FFFFFFFFFFFF0000000000000000FFFFFFFFFFFF000000 +000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00060B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0B0B0B0B0B0B0B0B0B05FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000FF00000000 +000000FFFFFFFF00000000000000000000000000000000000000FFFF00000000000000FF +FF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +000000000000000000000000000000000000FF0000000000000000FFFFFF000000000000 +00000000000000000000000000000000000000000000FFFF0000FFFFFFFFFF000000FFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF0000FFFFFFFF0000 +00FFFFFFFFFF0000FFFFFF000000FFFFFF0000FFFFFFFFFFFFFFFFFFFF000000FFFFFFFF +00000000FFFFFF0000FFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF0000FFFFFF0000 +00FFFFFF0000FFFFFFFFFFFFFFFFFFFF000000FFFFFF00000000FFFFFFFFFFFFFFFF0000 +FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FF +FFFFFFFFFFFFFFFF000000FFFFFFFFFF0000FFFFFF000000FFFFFF0000FFFFFFFFFFFFFF +FFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF0000FFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFFFF000000FFFF +FFFFFF0000000000000000FFFFFF0000000000000000FFFFFFFF000000FFFFFF000000FF +FFFFFFFFFFFFFFFF00000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF00000000000000FFFFFFFF000000FFFFFFFFFF00000000000000FFFFFF +FF0000000000000000FFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF0000000000 +0000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000 +00FFFFFFFF000000FFFFFFFFFF0000000000000000FFFFFF0000FFFFFFFFFFFFFFFFFFFF +000000FFFFFF000000FFFFFFFFFFFFFFFFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFF0000000000000000FF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF000000FFFFFFFFFF +0000FFFFFF000000FFFFFF0000FFFFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFF +FFFFFFFFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000 +00FFFF0000FF0000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000 +FF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF00FFFFFFFFFF000000FFFFFFFF000000FFFFFFFFFF0000FFFFFFFF000000FFFF0000 +FFFFFFFFFFFFFFFFFFFF000000FFFFFFFF000000FFFFFFFFFF00FFFF0000FFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFF0000FF00000000000000 +00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF000000FFFFFFFF +FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000FFFF +FFFF000000FFFFFFFFFF0000FFFFFFFF000000FFFF0000000000000000FFFFFFFF000000 +FFFFFFFF000000000000000000FFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFF000000FFFFFFFFFFFF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFF000000FFFFFFFFFF0000FF +FFFFFFFF000000FF0000000000000000FFFFFFFF000000FFFFFFFFFF0000000000000000 +FFFF0000FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF +0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF0000 +00FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FF0000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFF000000FFFF000000FFFFFFFFFFFF00 +0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +0000000000000000FFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +000000000000FFFF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFF0000FF +FFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF +000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF000000FFFFFFFFFFFF000000FF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000 +FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF +FFFFFFFFFF000000FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFF +FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF000000 +0000000000FF0000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF0000000000000000FF00000000000000 +00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF +FFFFFFFF0000FFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF0000FFFFFFFFFF0000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +end +%%PageTrailer +%%Trailer +%%EOF diff --git a/doc/img/emotion_ratio.png b/doc/img/emotion_ratio.png new file mode 100644 index 0000000..4ae37fd Binary files /dev/null and b/doc/img/emotion_ratio.png differ diff --git a/doc/img/foot_bg.png b/doc/img/foot_bg.png new file mode 100644 index 0000000..b24f3a4 Binary files /dev/null and b/doc/img/foot_bg.png differ diff --git a/doc/img/head_bg.png b/doc/img/head_bg.png new file mode 100644 index 0000000..081dc13 Binary files /dev/null and b/doc/img/head_bg.png differ diff --git a/doc/img/header_menu_background.png b/doc/img/header_menu_background.png new file mode 100644 index 0000000..e978743 Binary files /dev/null and b/doc/img/header_menu_background.png differ diff --git a/doc/img/header_menu_background_last.png b/doc/img/header_menu_background_last.png new file mode 100644 index 0000000..88c116c Binary files /dev/null and b/doc/img/header_menu_background_last.png differ diff --git a/doc/img/header_menu_current_background.png b/doc/img/header_menu_current_background.png new file mode 100644 index 0000000..de97c92 Binary files /dev/null and b/doc/img/header_menu_current_background.png differ diff --git a/doc/img/header_menu_unselected_background.png b/doc/img/header_menu_unselected_background.png new file mode 100644 index 0000000..50e5fd8 Binary files /dev/null and b/doc/img/header_menu_unselected_background.png differ diff --git a/doc/img/logo.png b/doc/img/logo.png new file mode 100644 index 0000000..b3884a5 Binary files /dev/null and b/doc/img/logo.png differ diff --git a/emotion-gstreamer.manifest b/emotion-gstreamer.manifest new file mode 100644 index 0000000..97e8c31 --- /dev/null +++ b/emotion-gstreamer.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/emotion.manifest b/emotion.manifest new file mode 100644 index 0000000..97e8c31 --- /dev/null +++ b/emotion.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/emotion.pc.in b/emotion.pc.in index f628489..5126c3b 100644 --- a/emotion.pc.in +++ b/emotion.pc.in @@ -5,8 +5,7 @@ includedir=@includedir@ 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@ diff --git a/emotion.spec.in b/emotion.spec.in index cc08edf..c6fa495 100644 --- a/emotion.spec.in +++ b/emotion.spec.in @@ -1,3 +1,4 @@ +%{!?_rel:%{expand:%%global _rel 0.enl%{?dist}}} %define _missing_doc_files_terminate_build 0 Summary: emotion @@ -65,10 +66,12 @@ test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT %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 diff --git a/m4/ac_attribute.m4 b/m4/ac_attribute.m4 new file mode 100644 index 0000000..3926d23 --- /dev/null +++ b/m4/ac_attribute.m4 @@ -0,0 +1,46 @@ +dnl Copyright (C) 2004-2008 Kim Woelders +dnl Copyright (C) 2008 Vincent Torri +dnl That code is public domain and can be freely used or copied. +dnl Originally snatched from somewhere... + +dnl Macro for checking if the compiler supports __attribute__ + +dnl Usage: AC_C___ATTRIBUTE__ +dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__ +dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is +dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused)) +dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is +dnl defined to nothing. + +AC_DEFUN([AC_C___ATTRIBUTE__], +[ + +AC_MSG_CHECKING([for __attribute__]) + +AC_CACHE_VAL([ac_cv___attribute__], + [AC_TRY_COMPILE( + [ +#include + +int func(int x); +int foo(int x __attribute__ ((unused))) +{ + exit(1); +} + ], + [], + [ac_cv___attribute__="yes"], + [ac_cv___attribute__="no"] + )] +) + +AC_MSG_RESULT($ac_cv___attribute__) + +if test "x${ac_cv___attribute__}" = "xyes" ; then + AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__]) + AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused]) + else + AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused]) +fi + +]) diff --git a/m4/efl_binary.m4 b/m4/efl_binary.m4 new file mode 100644 index 0000000..b9c9fd1 --- /dev/null +++ b/m4/efl_binary.m4 @@ -0,0 +1,44 @@ +dnl Copyright (C) 2010 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if a binary is built or not + +dnl Usage: EFL_ENABLE_BIN(binary[, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Call AC_SUBST(BINARY_PRG) (BINARY is the uppercase of binary, - being transformed into _) +dnl Define have_binary (- is transformed into _) +dnl Define conditional BUILD_BINARY (BINARY is the uppercase of binary, - being transformed into _) + +AC_DEFUN([EFL_ENABLE_BIN], +[ + +m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl + +have_[]m4_defn([DOWN])="yes" + +dnl configure option + +AC_ARG_ENABLE([$1], + [AC_HELP_STRING([--disable-$1], [disable building of ]DOWN)], + [ + if test "x${enableval}" = "xyes" ; then + have_[]m4_defn([DOWN])="yes" + else + have_[]m4_defn([DOWN])="no" + fi + ]) + +AC_MSG_CHECKING([whether to build ]DOWN[ binary]) +AC_MSG_RESULT([$have_[]m4_defn([DOWN])]) + +if test "x$have_[]m4_defn([DOWN])" = "xyes"; then + UP[]_PRG=DOWN[${EXEEXT}] +fi + +AC_SUBST(UP[]_PRG) + +AM_CONDITIONAL(BUILD_[]UP, test "x$have_[]m4_defn([DOWN])" = "xyes") + +AS_IF([test "x$have_[]m4_defn([DOWN])" = "xyes"], [$2], [$3]) + +]) diff --git a/m4/efl_doxygen.m4 b/m4/efl_doxygen.m4 new file mode 100644 index 0000000..7324af3 --- /dev/null +++ b/m4/efl_doxygen.m4 @@ -0,0 +1,94 @@ +dnl Copyright (C) 2008 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if doxygen is available or not. + +dnl EFL_CHECK_DOXYGEN([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Test for the doxygen program +dnl Defines efl_doxygen +dnl Defines the automake conditionnal EFL_BUILD_DOC +dnl +AC_DEFUN([EFL_CHECK_DOXYGEN], +[ + +dnl +dnl Disable the build of the documentation +dnl +AC_ARG_ENABLE([doc], + [AC_HELP_STRING( + [--disable-doc], + [Disable documentation build @<:@default=enabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + efl_enable_doc="yes" + else + efl_enable_doc="no" + fi + ], + [efl_enable_doc="yes"]) + +AC_MSG_CHECKING([whether to build documentation]) +AC_MSG_RESULT([${efl_enable_doc}]) + +if test "x${efl_enable_doc}" = "xyes" ; then + +dnl Specify the file name, without path + + efl_doxygen="doxygen" + + AC_ARG_WITH([doxygen], + [AC_HELP_STRING( + [--with-doxygen=FILE], + [doxygen program to use @<:@default=doxygen@:>@])], + +dnl Check the given doxygen program. + + [efl_doxygen=${withval} + AC_CHECK_PROG([efl_have_doxygen], + [${efl_doxygen}], + [yes], + [no]) + if test "x${efl_have_doxygen}" = "xno" ; then + echo "WARNING:" + echo "The doxygen program you specified:" + echo "${efl_doxygen}" + echo "was not found. Please check the path and make sure " + echo "the program exists and is executable." + AC_MSG_WARN([no doxygen detected. Documentation will not be built]) + fi + ], + [AC_CHECK_PROG([efl_have_doxygen], + [${efl_doxygen}], + [yes], + [no]) + if test "x${efl_have_doxygen}" = "xno" ; then + echo "WARNING:" + echo "The doxygen program was not found in your execute path." + echo "You may have doxygen installed somewhere not covered by your path." + echo "" + echo "If this is the case make sure you have the packages installed, AND" + echo "that the doxygen program is in your execute path (see your" + echo "shell manual page on setting the \$PATH environment variable), OR" + echo "alternatively, specify the program to use with --with-doxygen." + AC_MSG_WARN([no doxygen detected. Documentation will not be built]) + fi + ]) +else + efl_have_doxygen="no" +fi + +dnl +dnl Substitution +dnl +AC_SUBST([efl_doxygen]) + +if ! test "x${efl_have_doxygen}" = "xyes" ; then + efl_enable_doc="no" +fi + +AM_CONDITIONAL(EFL_BUILD_DOC, test "x${efl_have_doxygen}" = "xyes") + +AS_IF([test "x$efl_have_doxygen" = "xyes"], [$1], [$2]) +]) + +dnl End of efl_doxygen.m4 diff --git a/m4/efl_edje_external.m4 b/m4/efl_edje_external.m4 new file mode 100644 index 0000000..703f83e --- /dev/null +++ b/m4/efl_edje_external.m4 @@ -0,0 +1,56 @@ +dnl Copyright (C) 2010-2011 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if edje external should be enabled or not + +dnl Usage: EFL_EDJE_EXTERNAL([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Call AC_SUBST(EDJE_EXTERNAL_CFLAGS) +dnl Call AC_SUBST(EDJE_EXTERNAL_LIBS) +dnl Define conditional ENABLE_EDJE_EXTERNAL + +AC_DEFUN([EFL_EDJE_EXTERNAL], +[ + +AC_ARG_ENABLE([edje-external], + [AC_HELP_STRING([--disable-edje-external], + [disable providing Edje EXTERNAL support. @<:@default=enabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_want_edje_external="yes" + else + _efl_want_edje_external="no" + fi + ], + [_efl_want_edje_external="auto"]) + +AC_MSG_CHECKING([if should provide Edje EXTERNAL support...]) +AC_MSG_RESULT([${_efl_want_edje_external}]) + +_efl_enable_edje_external="no" +if ! test "x${_efl_want_edje_external}" = "xno" ; then + PKG_CHECK_MODULES([EDJE_EXTERNAL], + [edje >= 1.0.0], + [_efl_enable_edje_external="yes"], + [_efl_enable_edje_external="no"]) +fi + +AC_SUBST(EDJE_EXTERNAL_CFLAGS) +AC_SUBST(EDJE_EXTERNAL_LIBS) + +if test "x${_efl_want_edje_external}" = "xyes" && test "x${_efl_enable_edje_external}" = "xno" ; then + AC_MSG_ERROR([Edje EXTERNAL support requested, but Edje not found by pkg-config.]) +fi + +if test "x${_efl_enable_edje_external}" = "xyes" ; then + EDJE_VERSION=`${PKG_CONFIG} edje --modversion | awk -F . '{printf("%s.0.0", $[]1);}'` + MODULE_EDJE="$host_os-$host_cpu-${EDJE_VERSION}" + AC_DEFINE_UNQUOTED(MODULE_EDJE, "$MODULE_EDJE", "Edje module architecture") +fi + +AC_SUBST(MODULE_EDJE) + +AM_CONDITIONAL([ENABLE_EDJE_EXTERNAL], [test "x${_efl_enable_edje_external}" = "xyes"]) + +AS_IF([test "x${_efl_enable_edje_external}" = "xyes"], [$1], [$2]) + +]) diff --git a/m4/efl_examples.m4 b/m4/efl_examples.m4 new file mode 100644 index 0000000..2a809ad --- /dev/null +++ b/m4/efl_examples.m4 @@ -0,0 +1,63 @@ +dnl Copyright (C) 2008 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if building examples is wanted. + +dnl Usage: EFL_CHECK_BUILD_EXAMPLES([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Defines the automake conditionnal EFL_ENABLE_BUILD_EXAMPLES + +AC_DEFUN([EFL_CHECK_BUILD_EXAMPLES], +[ + +dnl configure option + +AC_ARG_ENABLE([build-examples], + [AC_HELP_STRING([--enable-build-examples], [enable building examples @<:@default=disabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_enable_build_examples="yes" + else + _efl_enable_build_examples="no" + fi + ], + [_efl_enable_build_examples="no"]) + +AC_MSG_CHECKING([whether examples are built]) +AC_MSG_RESULT([${_efl_enable_build_examples}]) + +AM_CONDITIONAL(EFL_BUILD_EXAMPLES, test "x${_efl_enable_build_examples}" = "xyes") + +AS_IF([test "x$_efl_enable_build_examples" = "xyes"], [$1], [$2]) +]) + + +dnl Macro that check if installing examples is wanted. + +dnl Usage: EFL_CHECK_INSTALL_EXAMPLES([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Defines the automake conditionnal EFL_ENABLE_INSTALL_EXAMPLES + +AC_DEFUN([EFL_CHECK_INSTALL_EXAMPLES], +[ + +dnl configure option + +AC_ARG_ENABLE([install-examples], + [AC_HELP_STRING([--enable-install-examples], [enable installing example source files @<:@default=disabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_enable_install_examples="yes" + else + _efl_enable_install_examples="no" + fi + ], + [_efl_enable_install_examples="no"]) + +AC_MSG_CHECKING([whether examples are installed]) +AC_MSG_RESULT([${_efl_enable_install_examples}]) + +AM_CONDITIONAL(EFL_INSTALL_EXAMPLES, test "x${_efl_enable_install_examples}" = "xyes") + +AS_IF([test "x$_efl_enable_install_examples" = "xyes"], [$1], [$2]) +]) + +dnl End of efl_examples.m4 diff --git a/m4/efl_shm_open.m4 b/m4/efl_shm_open.m4 new file mode 100644 index 0000000..0bf1b0b --- /dev/null +++ b/m4/efl_shm_open.m4 @@ -0,0 +1,69 @@ +dnl Copyright (C) 2010 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if shm_open function is available or not. + +dnl Usage: EFL_CHECK_SHM_OPEN([, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Call AC_SUBST(EFL_SHM_OPEN_LIBS) +dnl Define HAVE_SHM_OPEN to 1if shm_open is available + +AC_DEFUN([EFL_CHECK_SHM_OPEN], +[ +_efl_have_shm_open="no" + +dnl Check is shm_open is in libc + +AC_MSG_CHECKING([for shm_open in libc]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include /* For mode constants */ +#include /* For O_* constants */ + ]], + [[ +int fd; + +fd = shm_open("/dev/null", O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + ]])], + [_efl_have_shm_open="yes"], + [_efl_have_shm_open="no"]) + +AC_MSG_RESULT([${_efl_have_shm_open}]) + +if test "x$_efl_have_shm_open" = "xno" ; then + AC_MSG_CHECKING([for shm_open in librt]) + + LIBS_save="${LIBS}" + LIBS="${LIBS} -lrt" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include /* For mode constants */ +#include /* For O_* constants */ + ]], + [[ +int fd; + +fd = shm_open("/dev/null", O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + ]])], + [ + EFL_SHM_OPEN_LIBS="-lrt" + _efl_have_shm_open="yes"], + [_efl_have_shm_open="no"]) + + LIBS="${LIBS_save}" + + AC_MSG_RESULT([${_efl_have_shm_open}]) +fi + +AC_SUBST([EFL_SHM_OPEN_LIBS]) + +if test "x$_efl_have_shm_open" = "xyes" ; then + AC_DEFINE([HAVE_SHM_OPEN], [1], [Define to 1 if you have the `shm_open' function.]) +fi + +AS_IF([test "x$_efl_have_shm_open" = "xyes"], [$1], [$2]) + +]) diff --git a/m4/emotion_check.m4 b/m4/emotion_check.m4 new file mode 100644 index 0000000..043ae44 --- /dev/null +++ b/m4/emotion_check.m4 @@ -0,0 +1,216 @@ + +dnl use: EMOTION_CHECK_DEP_XINE(want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EMOTION_CHECK_DEP_XINE], +[ + +requirement="" + +PKG_CHECK_MODULES([XINE], + [libxine >= 1.1.1 evas >= 1.0.0], + [ + have_dep="yes" + requirement="libxine" + ], + [have_dep="no"]) + +if test "x$1" = "xstatic" ; then + requirement_emotion="${requirement} ${requirement_emotion}" +fi + +AS_IF([test "x$have_dep" = "xyes"], [$2], [$3]) + +]) + +dnl use: EMOTION_CHECK_DEP_GSTREAMER(want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EMOTION_CHECK_DEP_GSTREAMER], +[ + +GST_REQS=0.10.2 +GSTPLUG_REQS=0.10.1 +GST_MAJORMINOR=0.10 + +requirement="" +PKG_CHECK_MODULES([GSTREAMER], + [gstreamer-$GST_MAJORMINOR >= $GST_REQS gstreamer-plugins-base-$GST_MAJORMINOR >= $GSTPLUG_REQS gstreamer-video-$GST_MAJORMINOR >= $GSTPLUG_REQS evas >= 1.0.0 eina >= 1.1.99], + [ + have_dep="yes" + requirement="gstreamer-$GST_MAJORMINOR gstreamer-plugins-base-$GST_MAJORMINOR" + ], + [have_dep="no"]) + +if test "x$1" = "xstatic" ; then + requirement_emotion="${requirement} ${requirement_emotion}" +fi + +AS_IF([test "x$have_dep" = "xyes"], [$2], [$3]) + +]) + +dnl use: EMOTION_CHECK_DEP_GENERIC_VLC(want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EMOTION_CHECK_DEP_GENERIC_VLC], +[ + +requirement="" + +PKG_CHECK_MODULES([GENERIC_VLC], + [libvlc >= 0.9 eina >= 1.1.99], + [ + have_dep="yes" + requirement="libvlc" + ], + [have_dep="no"]) + +if test "x$1" = "xstatic" ; then + requirement_emotion="${requirement} ${requirement_emotion}" +fi + +AS_IF([test "x$have_dep" = "xyes"], [$2], [$3]) + +]) + +dnl use: EMOTION_CHECK_DEP_GENERIC(want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EMOTION_CHECK_DEP_GENERIC], +[ + +requirement="" + +PKG_CHECK_MODULES([GENERIC], + [evas >= 1.0.0], + [ + have_dep="yes" + ], + [have_dep="no"]) + +if test "x$1" = "xstatic" ; then + requirement_emotion="${requirement} ${requirement_emotion}" +fi + +AS_IF([test "x$have_dep" = "xyes"], [$2], [$3]) + +]) + +dnl use: EMOTION_CHECK_MODULE(description, want_module[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +AC_DEFUN([EMOTION_CHECK_MODULE], +[ +m4_pushdef([UP], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([$1], [-A-Z], [_a-z]))dnl + +want_module="$2" + +AC_ARG_ENABLE([DOWN], + [AC_HELP_STRING([--enable-]DOWN, [enable build of $1 module @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + enable_module="yes" + else + if test "x${enableval}" = "xstatic" ; then + enable_module="static" + else + enable_module="no" + fi + fi + ], + [enable_module="yes"]) + +if test "x${enable_module}" = "xyes" || test "x${enable_module}" = "xstatic" ; then + want_module="yes" +fi + +have_module="no" +if test "x${want_module}" = "xyes" && (test "x${enable_module}" = "xyes" || test "x${enable_module}" = "xstatic") ; then + m4_default([EMOTION_CHECK_DEP_]m4_defn([UP]))(${enable_module}, [have_module="yes"], [have_module="no"]) +fi + +AC_MSG_CHECKING([whether to enable $1 module built]) +AC_MSG_RESULT([${have_module}]) + +static_module="no" +if test "x${have_module}" = "xyes" && test "x${enable_module}" = "xstatic" ; then + static_module="yes" +fi + +AM_CONDITIONAL(EMOTION_BUILD_[]UP, [test "x${have_module}" = "xyes"]) +AM_CONDITIONAL(EMOTION_STATIC_BUILD_[]UP, [test "x${static_module}" = "xyes"]) + +if test "x${static_module}" = "xyes" ; then + AC_DEFINE(EMOTION_STATIC_BUILD_[]UP, 1, [Set to 1 if $1 is statically built]) + have_static_module="yes" +fi + +enable_[]DOWN="no" +if test "x${have_module}" = "xyes" ; then + enable_[]DOWN=${enable_module} + AC_DEFINE(EMOTION_BUILD_[]UP, 1, [Set to 1 if $1 is built]) +fi + +AS_IF([test "x$have_module" = "xyes"], [$3], [$4]) + +m4_popdef([UP]) +m4_popdef([DOWN]) +]) + +dnl use: EMOTION_CHECK_GENERIC_PLAYER(description, want_module[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +AC_DEFUN([EMOTION_CHECK_GENERIC_PLAYER], +[ +m4_pushdef([UP], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([$1], [-A-Z], [_a-z]))dnl + +want_module="$2" + +AC_ARG_ENABLE(generic-[]DOWN, + [AC_HELP_STRING([--enable-generic-]DOWN, [enable build of Generic Player $1 @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + enable_module="yes" + else + enable_module="no" + fi + ], + [enable_module="auto"]) + +# shm_open +EFL_CHECK_SHM_OPEN([have_shm_open="yes"], [have_shm_open="no"]) + +if test "x${have_shm_open}" != "xyes"; then + enable_generic="no" +fi + +if test "x${enable_generic}" != "xyes" && test "x${enable_generic}" != "xstatic"; then + if test "x${enable_module}" = "xyes"; then + AC_MSG_WARN([Generic module is disabled, force disable of Generic Player $1]) + fi + enable_module="no" + want_module="no" +fi + +if test "x${enable_module}" = "xauto"; then + enable_module="${want_module}" +elif test "x${enable_module}" = "xyes"; then + want_module="yes" +fi + +have_module="no" +if test "x${want_module}" = "xyes" && test "x${enable_module}" = "xyes"; then + m4_default([EMOTION_CHECK_DEP_GENERIC_]m4_defn([UP]))(${enable_module}, [have_module="yes"], [have_module="no"]) +fi + +AC_MSG_CHECKING([Whether to enable Generic Player $1]) +AC_MSG_RESULT([${have_module}]) + +AM_CONDITIONAL(EMOTION_BUILD_GENERIC_[]UP, [test "x${have_module}" = "xyes"]) + +enable_generic_[]DOWN="no" +if test "x${have_module}" = "xyes" ; then + enable_generic_[]DOWN=${enable_module} + AC_DEFINE(EMOTION_BUILD_GENERIC_[]UP, 1, [Set to 1 if $1 is built]) +fi + +AS_IF([test "x$have_module" = "xyes"], [$3], [$4]) + +m4_popdef([UP]) +m4_popdef([DOWN]) +]) diff --git a/packaging/emotion.spec b/packaging/emotion.spec new file mode 100644 index 0000000..30b06c7 --- /dev/null +++ b/packaging/emotion.spec @@ -0,0 +1,107 @@ +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 diff --git a/src/Makefile.am b/src/Makefile.am index 2ab111e..4082c3a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,12 @@ 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 diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index a90d598..79dd4e3 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -7,16 +7,20 @@ AM_CPPFLAGS = \ -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 diff --git a/src/bin/emotion_test_main.c b/src/bin/emotion_test_main.c index 16bb1a5..13380d6 100644 --- a/src/bin/emotion_test_main.c +++ b/src/bin/emotion_test_main.c @@ -1,22 +1,45 @@ -#include "config.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include -#if defined(HAVE_ECORE_X_H) || defined(HAVE_ECORE_FB_H) - #include #include -#ifndef FB_ONLY -#include -#else -#include -#endif +#include #include #include #include "Emotion.h" +static const Ecore_Getopt options = { + "emotion_test", + "%prog [options] ", + "1.0.0", + "(C) 2011 Enlightenment", + "BSD\nThis is a 3 clause bsd bla bla", + "a simple test program for emotion.", + 1, + { + ECORE_GETOPT_STORE_STR('e', "engine", "ecore-evas engine to use"), + ECORE_GETOPT_CALLBACK_NOARGS('E', "list-engines", "list ecore-evas engines", + ecore_getopt_callback_ecore_evas_list_engines, NULL), + ECORE_GETOPT_CALLBACK_ARGS('g', "geometry", "geometry to use in x:y:w:h form.", "X:Y:W:H", + ecore_getopt_callback_geometry_parse, NULL), + ECORE_GETOPT_STORE_STR('b', "backend", "backend to use"), + ECORE_GETOPT_STORE_INT('v', "vis", "visualization type"), + ECORE_GETOPT_COUNT('v', "verbose", "be more verbose"), + ECORE_GETOPT_STORE_TRUE('R', "reflex", "show video reflex effect"), + ECORE_GETOPT_VERSION('V', "version"), + ECORE_GETOPT_COPYRIGHT('R', "copyright"), + ECORE_GETOPT_LICENSE('L', "license"), + ECORE_GETOPT_HELP('h', "help"), + ECORE_GETOPT_SENTINEL + } +}; + typedef struct _Frame_Data Frame_Data; struct _Frame_Data @@ -27,10 +50,8 @@ 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); @@ -45,125 +66,35 @@ static Evas *evas = NULL; 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(); } @@ -193,23 +124,20 @@ bg_resize(Evas_Coord w, Evas_Coord h) 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")) @@ -252,77 +180,48 @@ bg_key_down(void *data, Evas * e, Evas_Object * obj, void *event_info) 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")) @@ -366,86 +265,49 @@ bg_key_down(void *data, Evas * e, Evas_Object * obj, void *event_info) { 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); @@ -455,7 +317,13 @@ video_obj_frame_decode_cb(void *data, Evas_Object *obj, void *event_info) 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) { @@ -468,7 +336,7 @@ video_obj_frame_decode_cb(void *data, Evas_Object *obj, void *event_info) } 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; @@ -489,46 +357,28 @@ video_obj_frame_resize_cb(void *data, Evas_Object *obj, void *event_info) } 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), @@ -536,52 +386,37 @@ video_obj_channels_cb(void *data, Evas_Object *obj, void *event_info) } 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)); } @@ -589,58 +424,50 @@ video_obj_button_cb(void *data, Evas_Object *obj, void *event_info) 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); @@ -649,7 +476,7 @@ video_obj_signal_speed_cb(void *data, Evas_Object *o, const char *emission, cons } 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; @@ -663,7 +490,7 @@ video_obj_signal_frame_move_start_cb(void *data, Evas_Object *o, const char *emi } 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; @@ -672,7 +499,7 @@ video_obj_signal_frame_move_stop_cb(void *data, Evas_Object *o, const char *emis } 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; @@ -686,7 +513,7 @@ video_obj_signal_frame_resize_start_cb(void *data, Evas_Object *o, const char *e } 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; @@ -695,7 +522,7 @@ video_obj_signal_frame_resize_stop_cb(void *data, Evas_Object *o, const char *em } 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; @@ -724,7 +551,7 @@ video_obj_signal_frame_move_cb(void *data, Evas_Object *o, const char *emission, 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; @@ -736,7 +563,12 @@ init_video_object(char *module_filename, char *filename) 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); @@ -745,7 +577,7 @@ init_video_object(char *module_filename, char *filename) /* 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; @@ -754,7 +586,10 @@ init_video_object(char *module_filename, char *filename) 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); @@ -767,6 +602,7 @@ init_video_object(char *module_filename, char *filename) 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); @@ -796,84 +632,117 @@ init_video_object(char *module_filename, char *filename) 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 : ""); + printf("emotion backend: %s\n", backend ? backend : ""); + printf("vis: %d\n", vis); + printf("geometry: %d %d %dx%d\n", geometry.x, geometry.y, geometry.w, geometry.h); + + ecore_evas = ecore_evas_new + (engine, geometry.x, geometry.y, geometry.w, geometry.h, NULL); + if (!ecore_evas) + goto shutdown_edje; + +// ecore_evas_alpha_set(ecore_evas, EINA_TRUE); + + ecore_evas_callback_delete_request_set(ecore_evas, main_delete_request); + ecore_evas_callback_resize_set(ecore_evas, main_resize); + ecore_evas_title_set(ecore_evas, "Evas Media Test Program"); + ecore_evas_name_class_set(ecore_evas, "evas_media_test", "main"); + ecore_evas_show(ecore_evas); + evas = ecore_evas_get(ecore_evas); + evas_image_cache_set(evas, 8 * 1024 * 1024); + evas_font_cache_set(evas, 1 * 1024 * 1024); + evas_font_path_append(evas, PACKAGE_DATA_DIR"/data/fonts"); + + emotion_init(); + + bg_setup(); + + for (; args < argc; args++) + init_video_object(backend, argv[args]); + + ecore_animator_add(check_positions, NULL); ecore_main_loop_begin(); - main_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 diff --git a/src/edje_external/Makefile.am b/src/edje_external/Makefile.am new file mode 100644 index 0000000..9b36faf --- /dev/null +++ b/src/edje_external/Makefile.am @@ -0,0 +1,18 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EMOTION_CPPFLAGS@ \ +@EMOTION_CFLAGS@ \ +@EDJE_EXTERNAL_CFLAGS@ \ +@EFL_EMOTION_BUILD@ + +pkgdir = $(libdir)/edje/modules/emotion/$(MODULE_EDJE) +pkg_LTLIBRARIES = module.la + +module_la_SOURCES = emotion.c +module_la_LIBADD = @EMOTION_LIBS@ $(top_builddir)/src/lib/libemotion.la @EDJE_EXTERNAL_LIBS@ +module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +module_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/src/edje_external/emotion.c b/src/edje_external/emotion.c new file mode 100644 index 0000000..d7fc012 --- /dev/null +++ b/src/edje_external/emotion.c @@ -0,0 +1,516 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "Emotion.h" + +typedef struct _External_Emotion_Params External_Emotion_Params; +typedef struct _External_Emotion_Signals_Proxy_Context External_Emotion_Signals_Proxy_Context; + +struct _External_Emotion_Params +{ +#define _STR(M) const char *M +#define _BOOL(M) Eina_Bool M:1; Eina_Bool M##_exists:1 +#define _INT(M) int M; Eina_Bool M##_exists:1 +#define _DOUBLE(M) double M; Eina_Bool M##_exists:1 + _STR(file); + _BOOL(play); + _DOUBLE(position); + _BOOL(smooth_scale); + _DOUBLE(audio_volume); + _BOOL(audio_mute); + _INT(audio_channel); + _BOOL(video_mute); + _INT(video_channel); + _BOOL(spu_mute); + _INT(spu_channel); + _INT(chapter); + _DOUBLE(play_speed); + _DOUBLE(play_length); + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE +}; + +struct _External_Emotion_Signals_Proxy_Context +{ + const char *emission; + const char *source; + Evas_Object *edje; +}; + +static int _log_dom = -1; +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) +#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__) + +static const char *_external_emotion_engines[] = { +#ifdef EMOTION_BUILD_XINE + "xine", +#endif +#ifdef EMOTION_BUILD_GSTREAMER + "gstreamer", +#endif +#ifdef EMOTION_BUILD_GENERIC + "generic", +#endif + NULL, +}; + +static const char _external_emotion_engine_def[] = +#if defined(EMOTION_BUILD_XINE) + "xine"; +#elif defined(EMOTION_BUILD_GSTREAMER) + "gstreamer"; +#elif defined(EMOTION_BUILD_GENERIC) + "generic"; +#else + "impossible"; +#endif + +static void +_external_emotion_signal_proxy_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + External_Emotion_Signals_Proxy_Context *ctxt = data; + free(ctxt); +} + +static void +_external_emotion_signal_proxy_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + External_Emotion_Signals_Proxy_Context *ctxt = data; + // TODO: Is it worth to check Evas_Smart_Cb_Description and do something + // TODO: with event_info given its description? + edje_object_signal_emit(ctxt->edje, ctxt->emission, ctxt->source); +} + +static Evas_Object * +_external_emotion_add(void *data __UNUSED__, Evas *evas, Evas_Object *edje __UNUSED__, const Eina_List *params, const char *part_name) +{ + const Evas_Smart_Cb_Description **cls_descs, **inst_descs; + unsigned int cls_count, inst_count, total; + External_Emotion_Signals_Proxy_Context *ctxt; + Evas_Object *obj; + const char *engine; + + if (!edje_external_param_choice_get(params, "engine", &engine)) + engine = NULL; + if (!engine) engine = _external_emotion_engine_def; + + obj = emotion_object_add(evas); + if (!emotion_object_init(obj, engine)) + { + ERR("failed to initialize emotion with engine '%s'.", engine); + return NULL; + } + + evas_object_smart_callbacks_descriptions_get + (obj, &cls_descs, &cls_count, &inst_descs, &inst_count); + + total = cls_count + inst_count; + if (!total) goto end; + ctxt = malloc(sizeof(External_Emotion_Signals_Proxy_Context) * total); + if (!ctxt) goto end; + evas_object_event_callback_add + (obj, EVAS_CALLBACK_DEL, _external_emotion_signal_proxy_free_cb, ctxt); + + for (; cls_count > 0; cls_count--, cls_descs++, ctxt++) + { + const Evas_Smart_Cb_Description *d = *cls_descs; + ctxt->emission = d->name; + ctxt->source = part_name; + ctxt->edje = edje; + evas_object_smart_callback_add + (obj, d->name, _external_emotion_signal_proxy_cb, ctxt); + } + + for (; inst_count > 0; inst_count--, inst_descs++, ctxt++) + { + const Evas_Smart_Cb_Description *d = *inst_descs; + ctxt->emission = d->name; + ctxt->source = part_name; + ctxt->edje = edje; + evas_object_smart_callback_add + (obj, d->name, _external_emotion_signal_proxy_cb, ctxt); + } + + end: + return obj; +} + +static void +_external_emotion_signal(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *signal, const char *source) +{ + DBG("External Signal received: '%s' '%s'", signal, source); +} + +static void +_external_emotion_state_set(void *data __UNUSED__, Evas_Object *obj, const void *from_params, const void *to_params, float pos __UNUSED__) +{ + const External_Emotion_Params *p; + + if (to_params) p = to_params; + else if (from_params) p = from_params; + else return; + +#define _STR(M) if (p->M) emotion_object_##M##_set(obj, p->M) +#define _BOOL(M) if (p->M##_exists) emotion_object_##M##_set(obj, p->M) +#define _INT(M) if (p->M##_exists) emotion_object_##M##_set(obj, p->M) +#define _DOUBLE(M) if (p->M##_exists) emotion_object_##M##_set(obj, p->M) + _STR(file); + _BOOL(play); + //_DOUBLE(position); + if (p->position_exists) + WRN("position should not be set from state description! Ignored."); + _BOOL(smooth_scale); + _DOUBLE(audio_volume); + _BOOL(audio_mute); + _INT(audio_channel); + _BOOL(video_mute); + _INT(video_channel); + _BOOL(spu_mute); + _INT(spu_channel); + _INT(chapter); + _DOUBLE(play_speed); + if (p->play_length_exists) ERR("play_length is read-only"); + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE +} + +static Eina_Bool +_external_emotion_param_set(void *data __UNUSED__, Evas_Object *obj, const Edje_External_Param *param) +{ + if (!strcmp(param->name, "engine")) + { + // TODO + WRN("engine is a property that can be set only at object creation!"); + return EINA_FALSE; + } + +#define _STR(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING) \ + { \ + emotion_object_##M##_set(obj, param->s); \ + return EINA_TRUE; \ + } \ + } +#define _BOOL(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL) \ + { \ + emotion_object_##M##_set(obj, param->i); \ + return EINA_TRUE; \ + } \ + } +#define _INT(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT) \ + { \ + emotion_object_##M##_set(obj, param->i); \ + return EINA_TRUE; \ + } \ + } +#define _DOUBLE(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE) \ + { \ + emotion_object_##M##_set(obj, param->d); \ + return EINA_TRUE; \ + } \ + } + + if (0) {} // so else if works... + _STR(file) + _BOOL(play) + _DOUBLE(position) + _BOOL(smooth_scale) + _DOUBLE(audio_volume) + _BOOL(audio_mute) + _INT(audio_channel) + _BOOL(video_mute) + _INT(video_channel) + _BOOL(spu_mute) + _INT(spu_channel) + _INT(chapter) + _DOUBLE(play_speed) + else if (!strcmp(param->name, "play_length")) + { + ERR("play_length is read-only"); + return EINA_FALSE; + } + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE + + ERR("unknown parameter '%s' of type '%s'", + param->name, edje_external_param_type_str(param->type)); + + return EINA_FALSE; +} + +static Eina_Bool +_external_emotion_param_get(void *data __UNUSED__, const Evas_Object *obj, Edje_External_Param *param) +{ +#define _STR(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING) \ + { \ + param->s = emotion_object_##M##_get(obj); \ + return EINA_TRUE; \ + } \ + } +#define _BOOL(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL) \ + { \ + param->i = emotion_object_##M##_get(obj); \ + return EINA_TRUE; \ + } \ + } +#define _INT(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_INT) \ + { \ + param->i = emotion_object_##M##_get(obj); \ + return EINA_TRUE; \ + } \ + } +#define _DOUBLE(M) \ + else if (!strcmp(param->name, #M)) \ + { \ + if (param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE) \ + { \ + param->d = emotion_object_##M##_get(obj); \ + return EINA_TRUE; \ + } \ + } + + if (0) {} // so else if works... + _STR(file) + _BOOL(play) + _DOUBLE(position) + _BOOL(smooth_scale) + _DOUBLE(audio_volume) + _BOOL(audio_mute) + _INT(audio_channel) + _BOOL(video_mute) + _INT(video_channel) + _BOOL(spu_mute) + _INT(spu_channel) + _INT(chapter) + _DOUBLE(play_speed) + _DOUBLE(play_length) + //_INT(vis) +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE + + ERR("unknown parameter '%s' of type '%s'", + param->name, edje_external_param_type_str(param->type)); + + return EINA_FALSE; +} + +static void * +_external_emotion_params_parse(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const Eina_List *params) +{ + const Edje_External_Param *param; + const Eina_List *l; + External_Emotion_Params *p = calloc(1, sizeof(External_Emotion_Params)); + if (!p) return NULL; + + EINA_LIST_FOREACH(params, l, param) + { +#define _STR(M) \ + if (!strcmp(param->name, #M)) p->M = eina_stringshare_add(param->s) +#define _BOOL(M) \ + if (!strcmp(param->name, #M)) \ + { \ + p->M = param->i; \ + p->M##_exists = EINA_TRUE; \ + } +#define _INT(M) \ + if (!strcmp(param->name, #M)) \ + { \ + p->M = param->i; \ + p->M##_exists = EINA_TRUE; \ + } +#define _DOUBLE(M) \ + if (!strcmp(param->name, #M)) \ + { \ + p->M = param->d; \ + p->M##_exists = EINA_TRUE; \ + } + + _STR(file); + _BOOL(play); + _DOUBLE(position); + _BOOL(smooth_scale); + _DOUBLE(audio_volume); + _BOOL(audio_mute); + _INT(audio_channel); + _BOOL(video_mute); + _INT(video_channel); + _BOOL(spu_mute); + _INT(spu_channel); + _INT(chapter); + _DOUBLE(play_speed); + _DOUBLE(play_length); + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE + } + + return p; +} + +static void +_external_emotion_params_free(void *params) +{ + External_Emotion_Params *p = params; + +#define _STR(M) eina_stringshare_del(p->M) +#define _BOOL(M) do {} while (0) +#define _INT(M) do {} while (0) +#define _DOUBLE(M) do {} while (0) + _STR(file); + _BOOL(play); + _DOUBLE(position); + _BOOL(smooth_scale); + _DOUBLE(audio_volume); + _BOOL(audio_mute); + _INT(audio_channel); + _BOOL(video_mute); + _INT(video_channel); + _BOOL(spu_mute); + _INT(spu_channel); + _INT(chapter); + _DOUBLE(play_speed); + _DOUBLE(play_length); + //_INT(vis); +#undef _STR +#undef _BOOL +#undef _INT +#undef _DOUBLE + free(p); +} + +static const char * +_external_emotion_label_get(void *data __UNUSED__) +{ + return "Emotion"; +} + +static Evas_Object * +_external_emotion_icon_add(void *data __UNUSED__, Evas *e) +{ + Evas_Object *ic; + int w = 0, h = 0; + + ic = edje_object_add(e); + edje_object_file_set(ic, PACKAGE_DATA_DIR"/data/icon.edj", "icon"); + edje_object_size_min_get(ic, &w, &h); + if (w < 1) w = 20; + if (h < 1) h = 10; + evas_object_size_hint_min_set(ic, w, h); + evas_object_size_hint_max_set(ic, w, h); + + return ic; +} + +static const char * +_external_emotion_translate(void *data __UNUSED__, const char *orig) +{ + // in future, mark all params as translatable and use dgettext() + // with "emotion" text domain here. + return orig; +} + +static Edje_External_Param_Info _external_emotion_params[] = { + EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL + ("engine", _external_emotion_engine_def, _external_emotion_engines), + EDJE_EXTERNAL_PARAM_INFO_STRING("file"), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("play", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_DOUBLE("position"), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("smooth_scale", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_DOUBLE_DEFAULT("audio_volume", 0.9), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("audio_mute", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_INT_DEFAULT("audio_channel", 0), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("video_mute", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_INT_DEFAULT("video_channel", 0), + EDJE_EXTERNAL_PARAM_INFO_BOOL_DEFAULT("spu_mute", EINA_FALSE), + EDJE_EXTERNAL_PARAM_INFO_INT_DEFAULT("spu_channel", 0), + EDJE_EXTERNAL_PARAM_INFO_INT("chapter"), + EDJE_EXTERNAL_PARAM_INFO_DOUBLE_DEFAULT("play_speed", 1.0), + EDJE_EXTERNAL_PARAM_INFO_DOUBLE("play_length"), + //EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL("vis", ...), + EDJE_EXTERNAL_PARAM_INFO_SENTINEL +}; + +static const Edje_External_Type _external_emotion_type = { + .abi_version = EDJE_EXTERNAL_TYPE_ABI_VERSION, + .module = "emotion", + .module_name = "Emotion", + .add = _external_emotion_add, + .state_set = _external_emotion_state_set, + .signal_emit = _external_emotion_signal, + .param_set = _external_emotion_param_set, + .param_get = _external_emotion_param_get, + .params_parse = _external_emotion_params_parse, + .params_free = _external_emotion_params_free, + .label_get = _external_emotion_label_get, + .description_get = NULL, + .icon_add = _external_emotion_icon_add, + .preview_add = NULL, + .translate = _external_emotion_translate, + .parameters_info = _external_emotion_params, + .data = NULL +}; + +static Edje_External_Type_Info _external_emotion_types[] = +{ + {"emotion", &_external_emotion_type}, + {NULL, NULL} +}; + +static Eina_Bool +external_emotion_mod_init(void) +{ + _log_dom = eina_log_domain_register + ("emotion-externals", EINA_COLOR_LIGHTBLUE); + edje_external_type_array_register(_external_emotion_types); + return EINA_TRUE; +} + +static void +external_emotion_mod_shutdown(void) +{ + edje_external_type_array_unregister(_external_emotion_types); + eina_log_domain_unregister(_log_dom); + _log_dom = -1; +} + +EINA_MODULE_INIT(external_emotion_mod_init); +EINA_MODULE_SHUTDOWN(external_emotion_mod_shutdown); diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am new file mode 100644 index 0000000..7476f08 --- /dev/null +++ b/src/examples/Makefile.am @@ -0,0 +1,39 @@ +MAINTAINERCLEANFILES = Makefile.in + +examplesdir = $(datadir)/$(PACKAGE)/examples + +AM_CPPFLAGS = \ +-I. \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +@EMOTION_CFLAGS@ \ +@EMOTION_CPPFLAGS@ \ +@EMOTION_BIN_CFLAGS@ + +LDADD = \ + $(top_builddir)/src/lib/libemotion.la \ + @EMOTION_BIN_LIBS@ + +SRCS = \ + emotion_basic_example.c \ + emotion_generic_example.c \ + emotion_border_example.c \ + emotion_signals_example.c + +EXTRA_DIST = $(SRCS) + +examples_PROGRAMS = + +if EFL_INSTALL_EXAMPLES +filesdir = $(datadir)/$(PACKAGE)/examples +files_DATA = $(SRCS) +endif + +if EFL_BUILD_EXAMPLES +examples_PROGRAMS += \ + emotion_basic_example \ + emotion_generic_example \ + emotion_border_example \ + emotion_signals_example +endif + diff --git a/src/examples/emotion_basic_example.c b/src/examples/emotion_basic_example.c new file mode 100644 index 0000000..7e3e4c2 --- /dev/null +++ b/src/examples/emotion_basic_example.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +#define WIDTH (320) +#define HEIGHT (240) + +static void +_playback_started_cb(void *data, Evas_Object *o, void *event_info) +{ + printf("Emotion object started playback.\n"); +} + +int +main(int argc, const char *argv[]) +{ + Ecore_Evas *ee; + Evas *e; + Evas_Object *bg, *em; + const char *filename = NULL; + + if (argc < 2) + { + printf("One argument is necessary. Usage:\n"); + printf("\t%s \n", argv[0]); + } + + filename = argv[1]; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL); + if (!ee) + goto error; + + ecore_evas_show(ee); + + /* the canvas pointer, de facto */ + e = ecore_evas_get(ee); + + /* adding a background to this example */ + bg = evas_object_rectangle_add(e); + evas_object_name_set(bg, "our dear rectangle"); + evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */ + evas_object_move(bg, 0, 0); /* at canvas' origin */ + evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */ + evas_object_show(bg); + + /* Creating the emotion object */ + em = emotion_object_add(e); + emotion_object_init(em, NULL); + + evas_object_smart_callback_add( + em, "playback_started", _playback_started_cb, NULL); + + emotion_object_file_set(em, filename); + + evas_object_move(em, 0, 0); + evas_object_resize(em, WIDTH, HEIGHT); + evas_object_show(em); + + emotion_object_play_set(em, EINA_TRUE); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + return 0; + +error: + fprintf(stderr, "you got to have at least one evas engine built and linked" + " up to ecore-evas for this example to run properly.\n"); + + ecore_evas_shutdown(); + return -1; +} diff --git a/src/examples/emotion_border_example.c b/src/examples/emotion_border_example.c new file mode 100644 index 0000000..9df53f4 --- /dev/null +++ b/src/examples/emotion_border_example.c @@ -0,0 +1,238 @@ +#include +#include +#include +#include +#include +#include + +#define WIDTH (320) +#define HEIGHT (240) + +static Eina_List *filenames = NULL; +static Eina_List *curfile = NULL; + +static void +_playback_started_cb(void *data, Evas_Object *o, void *event_info) +{ + printf("Emotion object started playback.\n"); +} + +static Evas_Object * +_create_emotion_object(Evas *e) +{ + Evas_Object *em = emotion_object_add(e); + + emotion_object_init(em, "gstreamer"); + + evas_object_smart_callback_add( + em, "playback_started", _playback_started_cb, NULL); + + return em; +} + +static void +_on_key_down(void *data, Evas *e, Evas_Object *o, void *event_info) +{ + Evas_Event_Key_Down *ev = event_info; + Evas_Object *em = data; + + if (!strcmp(ev->keyname, "Return")) + { + emotion_object_play_set(em, EINA_TRUE); + } + else if (!strcmp(ev->keyname, "space")) + { + emotion_object_play_set(em, EINA_FALSE); + } + else if (!strcmp(ev->keyname, "Escape")) + { + ecore_main_loop_quit(); + } + else if (!strcmp(ev->keyname, "n")) + { + const char *file; + if (!curfile) + curfile = filenames; + else + curfile = eina_list_next(curfile); + file = eina_list_data_get(curfile); + fprintf(stderr, "playing next file: %s\n", file); + emotion_object_file_set(em, file); + } + else if (!strcmp(ev->keyname, "p")) + { + const char *file; + if (!curfile) + curfile = eina_list_last(filenames); + else + curfile = eina_list_prev(curfile); + file = eina_list_data_get(curfile); + fprintf(stderr, "playing next file: %s\n", file); + emotion_object_file_set(em, file); + } + else if (!strcmp(ev->keyname, "b")) + { + emotion_object_border_set(em, 0, 0, 50, 50); + } + else if (!strcmp(ev->keyname, "0")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_NONE); + } + else if (!strcmp(ev->keyname, "w")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_WIDTH); + } + else if (!strcmp(ev->keyname, "h")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_HEIGHT); + } + else if (!strcmp(ev->keyname, "2")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_BOTH); + } + else if (!strcmp(ev->keyname, "c")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_CROP); + } + else + { + fprintf(stderr, "unhandled key: %s\n", ev->keyname); + } +} + +static void +_frame_decode_cb(void *data, Evas_Object *o, void *event_info) +{ + // fprintf(stderr, "smartcb: frame_decode\n"); +} + +static void +_length_change_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: length_change: %0.3f\n", emotion_object_play_length_get(o)); +} + +static void +_position_update_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: position_update: %0.3f\n", emotion_object_position_get(o)); +} + +static void +_progress_change_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: progress_change: %0.3f, %s\n", + emotion_object_progress_status_get(o), + emotion_object_progress_info_get(o)); +} + +static void +_frame_resize_cb(void *data, Evas_Object *o, void *event_info) +{ + int w, h; + emotion_object_size_get(o, &w, &h); + fprintf(stderr, "smartcb: frame_resize: %dx%d\n", w, h); +} + +static void /* adjust canvas' contents on resizes */ +_canvas_resize_cb(Ecore_Evas *ee) +{ + int w, h; + Evas_Object *bg, *em; + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + + bg = ecore_evas_data_get(ee, "bg"); + em = ecore_evas_data_get(ee, "emotion"); + + evas_object_resize(bg, w, h); + evas_object_move(em, 10, 10); + evas_object_resize(em, w - 20, h - 20); +} + +int +main(int argc, const char *argv[]) +{ + Ecore_Evas *ee; + Evas *e; + Evas_Object *bg, *em; + int i; + + if (argc < 2) + { + printf("One argument is necessary. Usage:\n"); + printf("\t%s \n", argv[0]); + } + + eina_init(); + for (i = 1; i < argc; i++) + filenames = eina_list_append(filenames, eina_stringshare_add(argv[i])); + + curfile = filenames; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL); + if (!ee) + goto error; + + ecore_evas_callback_resize_set(ee, _canvas_resize_cb); + + ecore_evas_show(ee); + + /* the canvas pointer, de facto */ + e = ecore_evas_get(ee); + + /* adding a background to this example */ + bg = evas_object_rectangle_add(e); + evas_object_name_set(bg, "our dear rectangle"); + evas_object_color_set(bg, 255, 0, 0, 255); /* white bg */ + evas_object_move(bg, 0, 0); /* at canvas' origin */ + evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */ + evas_object_show(bg); + + ecore_evas_data_set(ee, "bg", bg); + + /* Creating the emotion object */ + em = _create_emotion_object(e); + emotion_object_file_set(em, eina_list_data_get(curfile)); + evas_object_move(em, 10, 10); + evas_object_resize(em, WIDTH, HEIGHT); + evas_object_resize(em, WIDTH - 20, HEIGHT - 20); + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_BOTH); + emotion_object_bg_color_set(em, 0, 128, 0, 255); + evas_object_show(em); + + ecore_evas_data_set(ee, "emotion", em); + + evas_object_smart_callback_add(em, "frame_decode", _frame_decode_cb, NULL); + evas_object_smart_callback_add(em, "length_change", _length_change_cb, NULL); + evas_object_smart_callback_add(em, "position_update", _position_update_cb, NULL); + evas_object_smart_callback_add(em, "progress_change", _progress_change_cb, NULL); + evas_object_smart_callback_add(em, "frame_resize", _frame_resize_cb, NULL); + + evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, _on_key_down, em); + evas_object_focus_set(bg, EINA_TRUE); + + emotion_object_play_set(em, EINA_TRUE); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + return 0; + +error: + fprintf(stderr, "you got to have at least one evas engine built and linked" + " up to ecore-evas for this example to run properly.\n"); + + EINA_LIST_FREE(filenames, curfile) + eina_stringshare_del(eina_list_data_get(curfile)); + + ecore_evas_shutdown(); + eina_shutdown(); + return -1; +} diff --git a/src/examples/emotion_generic_example.c b/src/examples/emotion_generic_example.c new file mode 100644 index 0000000..b838286 --- /dev/null +++ b/src/examples/emotion_generic_example.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include +#include +#include +#include + +#define WIDTH (320) +#define HEIGHT (240) + +static Eina_List *filenames = NULL; +static Eina_List *curfile = NULL; + +static void +_playback_started_cb(void *data, Evas_Object *o, void *event_info) +{ + printf("Emotion object started playback.\n"); +} + +static void +_playback_stopped_cb(void *data, Evas_Object *o, void *event_info) +{ + printf("Emotion playback stopped.\n"); + emotion_object_play_set(o, EINA_FALSE); + emotion_object_position_set(o, 0); +} + +static Evas_Object * +_create_emotion_object(Evas *e) +{ + Evas_Object *em = emotion_object_add(e); + + emotion_object_init(em, "generic"); + + evas_object_smart_callback_add( + em, "playback_started", _playback_started_cb, NULL); + evas_object_smart_callback_add( + em, "playback_finished", _playback_stopped_cb, NULL); + + return em; +} + +static void +_on_key_down(void *data, Evas *e, Evas_Object *o, void *event_info) +{ + Evas_Event_Key_Down *ev = event_info; + Evas_Object *em = data; + + if (!strcmp(ev->keyname, "Return")) + { + emotion_object_play_set(em, EINA_TRUE); + } + else if (!strcmp(ev->keyname, "space")) + { + emotion_object_play_set(em, EINA_FALSE); + } + else if (!strcmp(ev->keyname, "Escape")) + { + ecore_main_loop_quit(); + } + else if (!strcmp(ev->keyname, "t")) + { + int w, h; + emotion_object_size_get(em, &w, &h); + fprintf(stderr, "example -> size: %dx%d\n", w, h); + } + else if (!strcmp(ev->keyname, "s")) + { + float len, pos; + len = emotion_object_play_length_get(em); + pos = 0.98 * len; + fprintf(stderr, "skipping to position %0.3f\n", pos); + emotion_object_position_set(em, pos); + } + else if (!strcmp(ev->keyname, "1")) + { + fprintf(stderr, "setting speed to 1.0\n"); + emotion_object_play_speed_set(em, 1.0); + } + else if (!strcmp(ev->keyname, "2")) + { + fprintf(stderr, "setting speed to 2.0\n"); + emotion_object_play_speed_set(em, 2.0); + } + else if (!strcmp(ev->keyname, "n")) + { + const char *file; + if (!curfile) + curfile = filenames; + else + curfile = eina_list_next(curfile); + file = eina_list_data_get(curfile); + fprintf(stderr, "playing next file: %s\n", file); + emotion_object_file_set(em, file); + } + else if (!strcmp(ev->keyname, "p")) + { + const char *file; + if (!curfile) + curfile = eina_list_last(filenames); + else + curfile = eina_list_prev(curfile); + file = eina_list_data_get(curfile); + fprintf(stderr, "playing next file: %s\n", file); + emotion_object_file_set(em, file); + } + else if (!strcmp(ev->keyname, "d")) + { + evas_object_del(em); + } + else if (!strcmp(ev->keyname, "l")) + { + // force frame dropping + sleep(5); + } + else + { + fprintf(stderr, "unhandled key: %s\n", ev->keyname); + } +} + +static void +_frame_decode_cb(void *data, Evas_Object *o, void *event_info) +{ + // fprintf(stderr, "smartcb: frame_decode\n"); +} + +static void +_length_change_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: length_change: %0.3f\n", emotion_object_play_length_get(o)); +} + +static void +_position_update_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: position_update: %0.3f\n", emotion_object_position_get(o)); +} + +static void +_progress_change_cb(void *data, Evas_Object *o, void *event_info) +{ + fprintf(stderr, "smartcb: progress_change: %0.3f, %s\n", + emotion_object_progress_status_get(o), + emotion_object_progress_info_get(o)); +} + +static void +_frame_resize_cb(void *data, Evas_Object *o, void *event_info) +{ + int w, h; + emotion_object_size_get(o, &w, &h); + fprintf(stderr, "smartcb: frame_resize: %dx%d\n", w, h); +} + +int +main(int argc, const char *argv[]) +{ + Ecore_Evas *ee; + Evas *e; + Evas_Object *bg, *em; + int i; + + if (argc < 2) + { + printf("One argument is necessary. Usage:\n"); + printf("\t%s \n", argv[0]); + } + + eina_init(); + for (i = 1; i < argc; i++) + filenames = eina_list_append(filenames, eina_stringshare_add(argv[i])); + + curfile = filenames; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL); + if (!ee) + goto error; + + ecore_evas_show(ee); + + /* the canvas pointer, de facto */ + e = ecore_evas_get(ee); + + /* adding a background to this example */ + bg = evas_object_rectangle_add(e); + evas_object_name_set(bg, "our dear rectangle"); + evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */ + evas_object_move(bg, 0, 0); /* at canvas' origin */ + evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */ + evas_object_show(bg); + + /* Creating the emotion object */ + em = _create_emotion_object(e); + emotion_object_file_set(em, eina_list_data_get(curfile)); + evas_object_move(em, 0, 0); + evas_object_resize(em, WIDTH, HEIGHT); + evas_object_show(em); + + evas_object_smart_callback_add(em, "frame_decode", _frame_decode_cb, NULL); + evas_object_smart_callback_add(em, "length_change", _length_change_cb, NULL); + evas_object_smart_callback_add(em, "position_update", _position_update_cb, NULL); + evas_object_smart_callback_add(em, "progress_change", _progress_change_cb, NULL); + evas_object_smart_callback_add(em, "frame_resize", _frame_resize_cb, NULL); + + evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, _on_key_down, em); + evas_object_focus_set(bg, EINA_TRUE); + + emotion_object_play_set(em, EINA_TRUE); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + return 0; + +error: + fprintf(stderr, "you got to have at least one evas engine built and linked" + " up to ecore-evas for this example to run properly.\n"); + + EINA_LIST_FREE(filenames, curfile) + eina_stringshare_del(eina_list_data_get(curfile)); + + ecore_evas_shutdown(); + eina_shutdown(); + return -1; +} diff --git a/src/examples/emotion_signals_example.c b/src/examples/emotion_signals_example.c new file mode 100644 index 0000000..2469c46 --- /dev/null +++ b/src/examples/emotion_signals_example.c @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include + +#define WIDTH (320) +#define HEIGHT (240) + +static void +_display_info(Evas_Object *o) +{ + int w, h; + printf("playing: %d\n", emotion_object_play_get(o)); + printf("meta title: %s\n", + emotion_object_meta_info_get(o, EMOTION_META_INFO_TRACK_TITLE)); + printf("seek position: %0.3f\n", + emotion_object_position_get(o)); + printf("play length: %0.3f\n", + emotion_object_play_length_get(o)); + printf("is seekable: %d\n", + emotion_object_seekable_get(o)); + emotion_object_size_get(o, &w, &h); + printf("video geometry: %dx%d\n", w, h); + printf("video width / height ratio: %0.3f\n", + emotion_object_ratio_get(o)); + printf("\n"); +} + +static void +_playback_started_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object started playback.\n"); + _display_info(o); +} + +static void +_playback_finished_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object finished playback.\n"); + _display_info(o); +} + +static void +_open_done_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object open done.\n"); + _display_info(o); +} + +static void +_position_update_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object first position update.\n"); + evas_object_smart_callback_del(o, "position_update", _position_update_cb); + _display_info(o); +} + +static void +_frame_decode_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object first frame decode.\n"); + evas_object_smart_callback_del(o, "frame_decode", _frame_decode_cb); + _display_info(o); +} + +static void +_decode_stop_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object decode stop.\n"); + _display_info(o); +} + +static void +_frame_resize_cb(void *data, Evas_Object *o, void *event_info) +{ + printf(">>> Emotion object frame resize.\n"); + _display_info(o); +} + +static void +_setup_emotion_callbacks(Evas_Object *o) +{ + evas_object_smart_callback_add( + o, "playback_started", _playback_started_cb, NULL); + evas_object_smart_callback_add( + o, "playback_finished", _playback_finished_cb, NULL); + evas_object_smart_callback_add( + o, "open_done", _open_done_cb, NULL); + evas_object_smart_callback_add( + o, "position_update", _position_update_cb, NULL); + evas_object_smart_callback_add( + o, "frame_decode", _frame_decode_cb, NULL); + evas_object_smart_callback_add( + o, "decode_stop", _decode_stop_cb, NULL); + evas_object_smart_callback_add( + o, "frame_resize", _frame_resize_cb, NULL); +} + +int +main(int argc, const char *argv[]) +{ + Ecore_Evas *ee; + Evas *e; + Evas_Object *bg, *em; + const char *filename = NULL; + const char *module = NULL; + + if (argc < 2) + { + printf("At least one argument is necessary. Usage:\n"); + printf("\t%s [module_name]\n", argv[0]); + goto error; + } + + filename = argv[1]; + + if (argc >= 3) + module = argv[2]; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL); + if (!ee) + goto error; + + ecore_evas_show(ee); + + /* the canvas pointer, de facto */ + e = ecore_evas_get(ee); + + /* adding a background to this example */ + bg = evas_object_rectangle_add(e); + evas_object_name_set(bg, "our dear rectangle"); + evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */ + evas_object_move(bg, 0, 0); /* at canvas' origin */ + evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */ + evas_object_show(bg); + + /* Creating the emotion object */ + em = emotion_object_add(e); + + /* Try to load the specified module - NULL for auto-discover */ + if (!emotion_object_init(em, module)) + fprintf(stderr, "Emotion: \"%s\" module could not be initialized.\n", module); + + _display_info(em); + _setup_emotion_callbacks(em); + + if (!emotion_object_file_set(em, filename)) + fprintf(stderr, "Emotion: Could not load the file \"%s\"\n", filename); + + evas_object_move(em, 0, 0); + evas_object_resize(em, WIDTH, HEIGHT); + evas_object_show(em); + + emotion_object_play_set(em, EINA_TRUE); + + ecore_main_loop_begin(); + + ecore_evas_free(ee); + ecore_evas_shutdown(); + return 0; + + ecore_evas_free(ee); + +error: + ecore_evas_shutdown(); + return -1; +} diff --git a/src/generic_players/Makefile.am b/src/generic_players/Makefile.am new file mode 100644 index 0000000..bbdd8c3 --- /dev/null +++ b/src/generic_players/Makefile.am @@ -0,0 +1,8 @@ + +MAINTAINERCLEANFILES = Makefile.in + +SUBDIRS = + +if EMOTION_BUILD_GENERIC_VLC +SUBDIRS += vlc +endif diff --git a/src/generic_players/vlc/Makefile.am b/src/generic_players/vlc/Makefile.am new file mode 100644 index 0000000..5cda1b9 --- /dev/null +++ b/src/generic_players/vlc/Makefile.am @@ -0,0 +1,18 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/modules \ +-I$(top_srcdir)/src/modules/generic \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@GENERIC_VLC_CFLAGS@ + +internal_bindir = $(libdir)/emotion/utils +internal_bin_PROGRAMS = em_generic_vlc + +em_generic_vlc_SOURCES = emotion_generic_vlc.c +em_generic_vlc_DEPENDENCIES = $(top_srcdir)/src/modules/generic/Emotion_Generic_Plugin.h +em_generic_vlc_LDADD = @GENERIC_VLC_LIBS@ @EFL_SHM_OPEN_LIBS@ -lpthread diff --git a/src/generic_players/vlc/emotion_generic_vlc.c b/src/generic_players/vlc/emotion_generic_vlc.c new file mode 100644 index 0000000..583036d --- /dev/null +++ b/src/generic_players/vlc/emotion_generic_vlc.c @@ -0,0 +1,873 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +enum _Thread_Events { + EM_THREAD_POSITION_CHANGED, + EM_THREAD_PLAYBACK_STARTED, + EM_THREAD_PLAYBACK_STOPPED, + EM_THREAD_LAST +}; + +struct _App { + Emotion_Generic_Video_Shared *vs; + Emotion_Generic_Video_Frame vf; + libvlc_instance_t *libvlc; + libvlc_media_t *m; + libvlc_media_player_t *mp; + libvlc_event_manager_t *event_mgr; + libvlc_event_manager_t *mevent_mgr; + char *filename; + char *shmname; + void *tmpbuffer; + int w, h; + int fd_read; // read commands from theads here + int fd_write; // write commands from threads here + int em_read; // read commands from emotion here + int em_write; // write commands to emotion here + int size_sent; + int opening; + int closing; + int playing; +}; + +static pthread_mutex_t _mutex_fd = PTHREAD_MUTEX_INITIALIZER; + +int +_em_read_safe(int fd, void *buf, ssize_t size) +{ + ssize_t todo; + char *p; + + todo = size; + p = buf; + + while (todo > 0) + { + ssize_t r; + + r = read(fd, p, todo); + if (r > 0) + { + todo -= r; + p += r; + } + else if (r == 0) + return 0; + else + { + if (errno == EINTR || errno == EAGAIN) + continue; + else + { + fprintf(stderr, "could not read from fd %d: %s", + fd, strerror(errno)); + return 0; + } + } + } + + return 1; +} + +int +_em_write_safe(int fd, const void *buf, ssize_t size) +{ + ssize_t todo; + const char *p; + + todo = size; + p = buf; + + while (todo > 0) + { + ssize_t r; + + r = write(fd, p, todo); + if (r > 0) + { + todo -= r; + p += r; + } + else if (r == 0) + return 0; + else + { + if (errno == EINTR || errno == EAGAIN) + continue; + else + { + fprintf(stderr, "could not write to fd %d: %s", + fd, strerror(errno)); + return 0; + } + } + } + + return 1; +} + +static int +_em_str_read(int fd, char **str) +{ + int size; + int r; + char buf[PATH_MAX]; + + r = _em_read_safe(fd, &size, sizeof(size)); + if (!r) + { + *str = NULL; + return 0; + } + + if (!size) + { + *str = NULL; + return 1; + } + + r = _em_read_safe(fd, buf, size); + if (!r) + { + *str = NULL; + return 0; + } + + *str = strdup(buf); + return 1; +} + +static int +_em_cmd_read(struct _App *app) +{ + int cmd; + _em_read_safe(app->em_read, &cmd, sizeof(cmd)); + + return cmd; +} + +static void +_send_cmd_start(struct _App *app, int cmd) +{ + pthread_mutex_lock(&_mutex_fd); + _em_write_safe(app->em_write, &cmd, sizeof(cmd)); +} + +static void +_send_cmd_finish(struct _App *app __UNUSED__) +{ + pthread_mutex_unlock(&_mutex_fd); +} + +static void +_send_cmd(struct _App *app, int cmd) +{ + _send_cmd_start(app, cmd); + _send_cmd_finish(app); +} + +static void +_send_cmd_str(struct _App *app, const char *str) +{ + int len; + if (str) + len = strlen(str) + 1; + else + len = 0; + _em_write_safe(app->em_write, &len, sizeof(len)); + _em_write_safe(app->em_write, str, len); +} + +#define SEND_CMD_PARAM(app, i) \ + _em_write_safe((app)->em_write, &(i), sizeof((i))); + +static void +_send_resize(struct _App *app, int width, int height) +{ + _send_cmd_start(app, EM_RESULT_FRAME_SIZE); + SEND_CMD_PARAM(app, width); + SEND_CMD_PARAM(app, height); + _send_cmd_finish(app); +} + +static void +_send_length_changed(struct _App *app, const struct libvlc_event_t *ev) +{ + float length = ev->u.media_player_length_changed.new_length; + length /= 1000; + + _send_cmd_start(app, EM_RESULT_LENGTH_CHANGED); + SEND_CMD_PARAM(app, length); + _send_cmd_finish(app); +} + +static void +_send_time_changed(struct _App *app, const struct libvlc_event_t *ev) +{ + float new_time = ev->u.media_player_time_changed.new_time; + new_time /= 1000; + if (app->vs->frame_drop > 1) + return; + _send_cmd_start(app, EM_RESULT_POSITION_CHANGED); + SEND_CMD_PARAM(app, new_time); + _send_cmd_finish(app); +} + +static void +_send_seekable_changed(struct _App *app, const struct libvlc_event_t *ev) +{ + int seekable = ev->u.media_player_seekable_changed.new_seekable; + _send_cmd_start(app, EM_RESULT_SEEKABLE_CHANGED); + SEND_CMD_PARAM(app, seekable); + _send_cmd_finish(app); +} + +static void * +_lock(void *data, void **pixels) +{ + struct _App *app = data; + + if (app->playing) + *pixels = app->vf.frames[app->vs->frame.player]; + else + *pixels = NULL; + + return NULL; // picture identifier, not needed here +} + +static void +_unlock(void *data __UNUSED__, void *id __UNUSED__, void *const *pixels __UNUSED__) +{ +} + +static void +_display(void *data, void *id __UNUSED__) +{ + struct _App *app = data; + if (!app->playing) + return; + + sem_wait(&app->vs->lock); + app->vs->frame.last = app->vs->frame.player; + app->vs->frame.player = app->vs->frame.next; + app->vs->frame.next = app->vs->frame.last; + if (!app->vs->frame_drop++) + _send_cmd(app, EM_RESULT_FRAME_NEW); + sem_post(&app->vs->lock); +} + +static void * +_tmp_lock(void *data, void **pixels) +{ + struct _App *app = data; + *pixels = app->tmpbuffer; + return NULL; +} + +static void +_tmp_unlock(void *data __UNUSED__, void *id __UNUSED__, void *const *pixels __UNUSED__) +{ +} + +static void +_tmp_display(void *data __UNUSED__, void *id __UNUSED__) +{ +} + +static void +_play(struct _App *app) +{ + float pos; + + if (!app->mp) + return; + + _em_read_safe(app->em_read, &pos, sizeof(pos)); + + if (app->playing) + { + libvlc_media_player_set_pause(app->mp, 0); + } + else + { + libvlc_time_t new_time = pos * 1000; + libvlc_media_player_set_time(app->mp, new_time); + libvlc_media_player_play(app->mp); + app->playing = 1; + } +} + +static void +_stop(struct _App *app) +{ + if (app->mp) + libvlc_media_player_set_pause(app->mp, 1); +} + +static void +_send_file_closed(struct _App *app) +{ + app->closing = 0; + emotion_generic_shm_free(app->vs); + _send_cmd(app, EM_RESULT_FILE_CLOSE); +} + +static void +_send_file_set(struct _App *app) +{ + if (app->opening) + _send_cmd(app, EM_RESULT_FILE_SET); + + if (app->closing) + _send_file_closed(app); +} + +static void +_event_cb(const struct libvlc_event_t *ev, void *data) +{ + struct _App *app = data; + int thread_event; + + switch (ev->type) { + case libvlc_MediaPlayerTimeChanged: + _send_time_changed(app, ev); + break; + case libvlc_MediaPlayerPositionChanged: + thread_event = EM_THREAD_POSITION_CHANGED; + write(app->fd_write, &thread_event, sizeof(thread_event)); + break; + case libvlc_MediaPlayerLengthChanged: + _send_length_changed(app, ev); + break; + case libvlc_MediaPlayerSeekableChanged: + _send_seekable_changed(app, ev); + break; + case libvlc_MediaPlayerPlaying: + _send_resize(app, app->w, app->h); + thread_event = EM_THREAD_PLAYBACK_STARTED; + write(app->fd_write, &thread_event, sizeof(thread_event)); + break; + case libvlc_MediaPlayerStopped: + _send_file_set(app); + break; + case libvlc_MediaPlayerEndReached: + thread_event = EM_THREAD_PLAYBACK_STOPPED; + write(app->fd_write, &thread_event, sizeof(thread_event)); + break; + } +} + +static void +_file_set(struct _App *app) +{ + if (app->opening) + { + libvlc_media_release(app->m); + libvlc_media_player_release(app->mp); + free(app->filename); + } + + _em_str_read(app->em_read, &app->filename); + + app->m = libvlc_media_new_path(app->libvlc, app->filename); + if (!app->m) + { + fprintf(stderr, "could not open path: \"%s\"\n", app->filename); + return; + } + + app->mp = libvlc_media_player_new_from_media(app->m); + if (!app->mp) + { + fprintf(stderr, "could not create new player from media.\n"); + return; + } + + app->opening = 1; + libvlc_video_set_format(app->mp, "RV32", DEFAULTWIDTH, DEFAULTHEIGHT, DEFAULTWIDTH * 4); + libvlc_video_set_callbacks(app->mp, _tmp_lock, _tmp_unlock, _tmp_display, app); + app->event_mgr = libvlc_media_player_event_manager(app->mp); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerPositionChanged, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerStopped, + _event_cb, app); + + app->mevent_mgr = libvlc_media_event_manager(app->m); + + app->tmpbuffer = malloc(sizeof(char) * DEFAULTWIDTH * DEFAULTHEIGHT * 4); + libvlc_audio_set_mute(app->mp, 1); + libvlc_media_player_play(app->mp); +} + +static void +_position_set(struct _App *app) +{ + if (!app->mp) + return; + + float position; + _em_read_safe(app->em_read, &position, sizeof(position)); + + libvlc_time_t new_time = position * 1000; + libvlc_media_player_set_time(app->mp, new_time); +} + +static void +_speed_set(struct _App *app) +{ + float rate; + + if (!app->mp) + return; + + _em_read_safe(app->em_read, &rate, sizeof(rate)); + + libvlc_media_player_set_rate(app->mp, rate); +} + +static void +_mute_set(struct _App *app) +{ + int mute; + + if (!app->mp) + return; + + _em_read_safe(app->em_read, &mute, sizeof(mute)); + + libvlc_audio_set_mute(app->mp, mute); +} + +static void +_volume_set(struct _App *app) +{ + float volume; + int vol; + + if (!app->mp) + return; + + _em_read_safe(app->em_read, &volume, sizeof(volume)); + vol = volume * 100; + + libvlc_audio_set_volume(app->mp, vol); +} + +static void +_spu_track_set(struct _App *app) +{ + int track; + + _em_read_safe(app->em_read, &track, sizeof(track)); + + libvlc_video_set_spu(app->mp, track); +} + +static void +_audio_track_set(struct _App *app) +{ + int track; + + _em_read_safe(app->em_read, &track, sizeof(track)); + + libvlc_audio_set_track(app->mp, track); +} + +static void +_video_track_set(struct _App *app) +{ + int track; + + _em_read_safe(app->em_read, &track, sizeof(track)); + + libvlc_video_set_track(app->mp, track); +} + +static void +_file_set_done(struct _App *app) +{ + int r; + + app->opening = 0; + + r = emotion_generic_shm_get(app->shmname, &app->vs, &app->vf); + if (!r) + { + free(app->filename); + libvlc_media_release(app->m); + libvlc_media_player_release(app->mp); + app->filename = NULL; + app->m = NULL; + app->mp = NULL; + _send_cmd_start(app, EM_RESULT_FILE_SET_DONE); + SEND_CMD_PARAM(app, r); + _send_cmd_finish(app); + } + app->w = app->vs->width; + app->h = app->vs->height; + libvlc_video_set_format(app->mp, "RV32", app->w, app->h, app->w * 4); + libvlc_video_set_callbacks(app->mp, _lock, _unlock, _display, app); + + + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerPlaying, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerTimeChanged, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerLengthChanged, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerSeekableChanged, + _event_cb, app); + libvlc_event_attach(app->event_mgr, libvlc_MediaPlayerEndReached, + _event_cb, app); + + libvlc_audio_set_mute(app->mp, 0); + + _send_cmd_start(app, EM_RESULT_FILE_SET_DONE); + SEND_CMD_PARAM(app, r); + _send_cmd_finish(app); +} + +static void +_file_close(struct _App *app) +{ + app->playing = 0; + if (app->opening) + goto release_resources; + + if (libvlc_media_player_get_state(app->mp) != libvlc_Playing) + { + _send_file_closed(app); + return; + } + + app->closing = 1; + +release_resources: + libvlc_media_player_stop(app->mp); + if (app->filename) + free(app->filename); + if (app->mp) + { + libvlc_media_release(app->m); + libvlc_media_player_release(app->mp); + free(app->tmpbuffer); + } +} + +static void +_process_emotion_commands(struct _App *app) +{ + int cmd = _em_cmd_read(app); + switch (cmd) { + case EM_CMD_FILE_SET: + _file_set(app); + break; + case EM_CMD_FILE_SET_DONE: + _file_set_done(app); + break; + case EM_CMD_FILE_CLOSE: + _file_close(app); + break; + case EM_CMD_PLAY: + _play(app); + break; + case EM_CMD_STOP: + _stop(app); + break; + case EM_CMD_POSITION_SET: + _position_set(app); + break; + case EM_CMD_SPEED_SET: + _speed_set(app); + break; + case EM_CMD_AUDIO_MUTE_SET: + _mute_set(app); + break; + case EM_CMD_VOLUME_SET: + _volume_set(app); + break; + case EM_CMD_SPU_TRACK_SET: + _spu_track_set(app); + break; + case EM_CMD_AUDIO_TRACK_SET: + _audio_track_set(app); + break; + case EM_CMD_VIDEO_TRACK_SET: + _video_track_set(app); + break; + }; +} + +static void +_send_track_info(struct _App *app, int cmd, int current, int count, libvlc_track_description_t *desc) +{ + _send_cmd_start(app, cmd); + SEND_CMD_PARAM(app, current); + SEND_CMD_PARAM(app, count); + while (desc) + { + int tid = desc->i_id; + const char *name = desc->psz_name; + SEND_CMD_PARAM(app, tid); + _send_cmd_str(app, name); + desc = desc->p_next; + } + _send_cmd_finish(app); +} + +static void +_send_all_track_info(struct _App *app) +{ + int track_count, current; + libvlc_track_description_t *desc; + + current = libvlc_audio_get_track(app->mp); + track_count = libvlc_audio_get_track_count(app->mp); + desc = libvlc_audio_get_track_description(app->mp); + + _send_track_info(app, EM_RESULT_AUDIO_TRACK_INFO, + current, track_count, desc); + + current = libvlc_video_get_track(app->mp); + track_count = libvlc_video_get_track_count(app->mp); + desc = libvlc_video_get_track_description(app->mp); + + _send_track_info(app, EM_RESULT_VIDEO_TRACK_INFO, + current, track_count, desc); + + current = libvlc_video_get_spu(app->mp); + track_count = libvlc_video_get_spu_count(app->mp); + desc = libvlc_video_get_spu_description(app->mp); + + _send_track_info(app, EM_RESULT_SPU_TRACK_INFO, + current, track_count, desc); +} + +static void +_send_all_meta_info(struct _App *app) +{ + const char *meta; + + _send_cmd_start(app, EM_RESULT_META_INFO); + + /* + * Will send in this order: title, artist, album, year, + * genre, comments, disc id and track count. + */ + meta = libvlc_media_get_meta(app->m, libvlc_meta_Title); + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_Artist); + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_Album); + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_Date); + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_Genre); + _send_cmd_str(app, meta); + meta = NULL; // sending empty comments + _send_cmd_str(app, meta); + meta = NULL; // sending empty disc id + _send_cmd_str(app, meta); + meta = libvlc_media_get_meta(app->m, libvlc_meta_TrackNumber); + _send_cmd_str(app, meta); + _send_cmd_finish(app); +} + +static void +_position_changed(struct _App *app) +{ + if (!app->opening) + return; + + /* sending size info only once */ + int r; + unsigned int w, h; + r = libvlc_video_get_size(app->mp, 0, &w, &h); + if (r < 0) + { + w = 1; + h = 1; + } + _send_resize(app, w, h); + + /* sending audio track info */ + _send_all_track_info(app); + + /* sending meta info */ + _send_all_meta_info(app); + + libvlc_media_player_stop(app->mp); +} + +static void +_process_thread_events(struct _App *app) +{ + int event; + size_t size; + + size = read(app->fd_read, &event, sizeof(event)); + if (size != sizeof(event)) + { + fprintf(stderr, "player: problem when reading thread event. size = %zd\n", size); + return; + } + + switch (event) { + case EM_THREAD_POSITION_CHANGED: + _position_changed(app); + break; + case EM_THREAD_PLAYBACK_STARTED: + _send_cmd(app, EM_RESULT_PLAYBACK_STARTED); + break; + case EM_THREAD_PLAYBACK_STOPPED: + app->playing = 0; + _send_cmd(app, EM_RESULT_PLAYBACK_STOPPED); + break; + } +} + +int +main(int argc, const char *argv[]) +{ + struct _App app; + struct pollfd fds[3]; + int tpipe[2]; // pipe for comunicating events from threads + char cwidth[64], cheight[64], cpitch[64], chroma[64]; + char buf[64]; + const char *vlc_argv[] = + { + "--quiet", + "--vout", + "vmem", + "--vmem-width", + cwidth, + "--vmem-height", + cheight, + "--vmem-pitch", + cpitch, + "--vmem-chroma", + chroma + }; + + if (argc < 3) + { + fprintf(stderr, "player: missing paramters.\n"); + fprintf(stderr, "syntax:\n\t%s \n", argv[0]); + return -1; + } + + app.em_read = atoi(argv[1]); + app.em_write = atoi(argv[2]); + + int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv); + snprintf(cwidth, sizeof(cwidth), "%d", DEFAULTWIDTH); + snprintf(cheight, sizeof(cheight), "%d", DEFAULTHEIGHT); + snprintf(cpitch, sizeof(cpitch), "%d", DEFAULTWIDTH * 4); + snprintf(chroma, sizeof(chroma), "RV32"); + + /* + * Naughty xattr in emotion uses ecore_thread to run its thing, this + * may leave emotion's reference count high and it won't kill us... + * letting us play the video in the background. not good. + * + * prctl(PR_SET_PDEATHSIG) is a linux only thing. Need to find ways + * to do it on other platforms. Until then leave it breaking on + * such platforms so people port it instead of ignoring. + */ + prctl(PR_SET_PDEATHSIG, SIGHUP); + + app.libvlc = libvlc_new(vlc_argc, vlc_argv); + app.mp = NULL; + app.filename = NULL; + app.w = 0; + app.h = 0; + app.size_sent = 0; + app.opening = 0; + app.playing = 0; + app.closing = 0; + + if (_em_cmd_read(&app) != EM_CMD_INIT) + { + fprintf(stderr, "player: wrong init command!\n"); + return -1; + } + + int size; + _em_read_safe(app.em_read, &size, sizeof(size)); + _em_read_safe(app.em_read, buf, size); + app.shmname = strdup(buf); + + _send_cmd(&app, EM_RESULT_INIT); + + pipe(tpipe); + app.fd_read = tpipe[0]; + app.fd_write = tpipe[1]; + fds[0].fd = app.em_read; + fds[0].events = POLLIN; + fds[1].fd = app.fd_read; + fds[1].events = POLLIN; + fds[2].fd = STDERR_FILENO; + fds[2].events = 0; + + while (1) + { + int r; + + r = poll(fds, 3, -1); + if (r == 0) + continue; + else if (r < 0) + { + fprintf(stderr, + "emotion_generic_vlc: an error ocurred on poll(): %s\n", + strerror(errno)); + break; + } + + if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) + { + fputs("emotion_generic_vlc: error communicating with stdin\n", + stderr); + break; + } + if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) + { + fputs("emotion_generic_vlc: error communicating with thread\n", + stderr); + break; + } + + if (fds[0].revents & POLLIN) + _process_emotion_commands(&app); + if (fds[1].revents & POLLIN) + _process_thread_events(&app); + if (fds[2].revents & (POLLERR | POLLHUP | POLLNVAL)) + break; + } + + libvlc_release(app.libvlc); + + + return 0; +} +#undef SEND_CMD_PARAM diff --git a/src/lib/Emotion.h b/src/lib/Emotion.h index e55757f..361e4e5 100644 --- a/src/lib/Emotion.h +++ b/src/lib/Emotion.h @@ -1,15 +1,97 @@ #ifndef EMOTION_H #define EMOTION_H +/** + * @file + * @brief Emotion Media Library + * + * These routines are used for Emotion. + */ + +/** + * + * @mainpage Emotion Library Documentation + * + * @version 1.7.0 + * @date 2003-2012 + * + * @section intro What is Emotion? + * + * A media object library for Evas and Ecore. + * + * Emotion is a library that allows playing audio and video files, using one of + * its backends (gstreamer or xine). + * + * It is integrated into Ecore through its mainloop, and is transparent to the + * user of the library how the decoding of audio and video is being done. Once + * the objects are created, the user can set callbacks to the specific events + * and set options to this object, all in the main loop (no threads are needed). + * + * Emotion is also integrated with Evas. The emotion object returned by + * emotion_object_add() is an Evas smart object, so it can be manipulated with + * default Evas object functions. Callbacks can be added to the signals emitted + * by this object with evas_object_smart_callback_add(). + * + * @section work How does Emotion work? + * + * The Emotion library uses Evas smart objects to allow you to manipulate the + * created object as any other Evas object, and to connect to its signals, + * handling them when needed. It's also possible to swallow Emotion objects + * inside Edje themes, and expect it to behave as a normal image or rectangle + * when regarding to its dimensions. + * + * To instantiate an Emotion object, the simple code below is enough: + * + * @code + * em = emotion_object_add(e); + * emotion_object_init(em, NULL); + * + * emotion_object_file_set(em, file_path); + * + * evas_object_move(em, 0, 0); + * evas_object_resize(em, WIDTH, HEIGHT); + * evas_object_show(em); + * + * emotion_object_play_set(em, EINA_TRUE); + * @endcode + * + * See the @ref Emotion_API for a better reference. + * + * Please see the @ref authors page for contact details. + * + */ + +/** + * + * @page authors Authors + * + * @author Carsten Haitzler + * @author Vincent Torri + * @author Nicolas Aguirre + * @author Sebastian Dransfeld + * @author Cedric Bail + * + * Please contact to get in + * contact with the developers and maintainers. + * + */ + +#include + #ifdef EAPI -#undef EAPI +# 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 @@ -20,9 +102,13 @@ # else # define EAPI # endif -#endif +#endif /* ! _WIN32 */ -#include +/** + * @file Emotion.h + * @brief The file that provides Emotion the API, with functions available for + * play, seek, change volume, etc. + */ enum _Emotion_Module { @@ -62,21 +148,97 @@ enum _Emotion_Event 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 @@ -84,64 +246,1037 @@ typedef enum _Emotion_Meta_Info Emotion_Meta_Info; #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 diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 34a4a2e..a2d2198 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -7,15 +7,53 @@ AM_CPPFLAGS = \ -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 diff --git a/src/lib/emotion_main.c b/src/lib/emotion_main.c new file mode 100644 index 0000000..52b1baa --- /dev/null +++ b/src/lib/emotion_main.c @@ -0,0 +1,484 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include +# define alloca _alloca +# elif !defined HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#include + +#ifdef EMOTION_HAVE_EEZE +# include +# include +# include +# include +# ifdef HAVE_V4L2 +# include +# endif + +# include +# include +#endif + +#include + +#include "Emotion.h" +#include "emotion_private.h" + +static Emotion_Version _version = { VMAJ, VMIN, VMIC, VREV }; +static int emotion_pending_objects = 0; +EAPI Emotion_Version *emotion_version = &_version; + +EAPI int EMOTION_WEBCAM_UPDATE = 0; + +struct ext_match_s +{ + unsigned int length; + const char *extension; +}; + +#define MATCHING(Ext) \ + { sizeof (Ext), Ext } + +static const struct ext_match_s matchs[] = +{ /* map extensions to know if it's a emotion playable content for good first-guess tries */ + MATCHING(".264"), + MATCHING(".3g2"), + MATCHING(".3gp"), + MATCHING(".3gp2"), + MATCHING(".3gpp"), + MATCHING(".3gpp2"), + MATCHING(".3p2"), + MATCHING(".asf"), + MATCHING(".avi"), + MATCHING(".bdm"), + MATCHING(".bdmv"), + MATCHING(".clpi"), + MATCHING(".clp"), + MATCHING(".fla"), + MATCHING(".flv"), + MATCHING(".m1v"), + MATCHING(".m2v"), + MATCHING(".m2t"), + MATCHING(".m4v"), + MATCHING(".mkv"), + MATCHING(".mov"), + MATCHING(".mp2"), + MATCHING(".mp2ts"), + MATCHING(".mp4"), + MATCHING(".mpe"), + MATCHING(".mpeg"), + MATCHING(".mpg"), + MATCHING(".mpl"), + MATCHING(".mpls"), + MATCHING(".mts"), + MATCHING(".mxf"), + MATCHING(".nut"), + MATCHING(".nuv"), + MATCHING(".ogg"), + MATCHING(".ogm"), + MATCHING(".ogv"), + MATCHING(".rm"), + MATCHING(".rmj"), + MATCHING(".rmm"), + MATCHING(".rms"), + MATCHING(".rmx"), + MATCHING(".rmvb"), + MATCHING(".swf"), + MATCHING(".ts"), + MATCHING(".weba"), + MATCHING(".webm"), + MATCHING(".wmv") +}; + +Eina_Bool +_emotion_object_extension_can_play_generic_get(const void *data __UNUSED__, const char *file) +{ + unsigned int length; + unsigned int i; + + length = eina_stringshare_strlen(file) + 1; + if (length < 5) return EINA_FALSE; + + for (i = 0; i < sizeof (matchs) / sizeof (struct ext_match_s); ++i) + { + if (matchs[i].length > length) continue; + + if (!strcasecmp(matchs[i].extension, + file + length - matchs[i].length)) + return EINA_TRUE; + } + + return EINA_FALSE; +} + +EAPI Eina_Bool +emotion_object_extension_may_play_fast_get(const char *file) +{ + if (!file) return EINA_FALSE; + return _emotion_object_extension_can_play_generic_get(NULL, file); +} + +EAPI Eina_Bool +emotion_object_extension_may_play_get(const char *file) +{ + const char *tmp; + Eina_Bool result; + + if (!file) return EINA_FALSE; + tmp = eina_stringshare_add(file); + result = emotion_object_extension_may_play_fast_get(tmp); + eina_stringshare_del(tmp); + + return result; +} + +typedef struct _Emotion_Webcams Emotion_Webcams; + +struct _Emotion_Webcams +{ + Eina_List *webcams; +}; + +struct _Emotion_Webcam +{ + EINA_REFCOUNT; + + const char *syspath; + const char *device; + const char *name; + + const char *custom; + + const char *filename; +}; + +static int _emotion_webcams_count = 0; +static Eet_Data_Descriptor *_webcam_edd; +static Eet_Data_Descriptor *_webcams_edd; + +static Emotion_Webcams *_emotion_webcams = NULL; +static Eet_File *_emotion_webcams_file = NULL; + +static Eet_Data_Descriptor * +_emotion_webcams_data(void) +{ + Eet_Data_Descriptor_Class eddc; + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcam); + _webcam_edd = eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "device", device, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "name", name, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "custom", custom, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "filename", filename, EET_T_STRING); + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcams); + _webcams_edd = eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_LIST(_webcams_edd, Emotion_Webcams, "webcams", webcams, _webcam_edd); + + return _webcams_edd; +} + +#ifdef EMOTION_HAVE_EEZE +static Eeze_Udev_Watch *eeze_watcher = NULL; + +static void +emotion_webcam_destroy(Emotion_Webcam *ew) +{ + if (!ew->custom) + { + eina_stringshare_del(ew->syspath); + eina_stringshare_del(ew->device); + eina_stringshare_del(ew->name); + } + free(ew); +} + +static void +_emotion_check_device(Emotion_Webcam *ew) +{ +#ifdef HAVE_V4L2 + Emotion_Webcam *check; + Eina_List *l; + struct v4l2_capability caps; + int fd; +#endif + + if (!ew) return ; +#ifdef HAVE_V4L2 + if (!ew->device) goto on_error; + + fd = open(ew->filename, O_RDONLY); + if (fd < 0) goto on_error; + + if (ioctl(fd, VIDIOC_QUERYCAP, &caps) == -1) goto on_error; + + /* Likely not a webcam */ + if (!caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) goto on_error; + if (caps.capabilities & V4L2_CAP_TUNER + || caps.capabilities & V4L2_CAP_RADIO + || caps.capabilities & V4L2_CAP_MODULATOR) + goto on_error; + + EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check) + if (check->device == ew->device) + goto on_error; + + _emotion_webcams->webcams = eina_list_append(_emotion_webcams->webcams, ew); + + EINA_REFCOUNT_INIT(ew); + + return ; + + on_error: +#endif + fprintf(stderr, "'%s' is not a webcam ['%s']\n", ew->name, strerror(errno)); + eina_stringshare_del(ew->syspath); + eina_stringshare_del(ew->device); + eina_stringshare_del(ew->name); + free(ew); +} + +static Emotion_Webcam * +_emotion_webcam_new(const char *syspath) +{ + Emotion_Webcam *test; + const char *device; + char *local; + + test = malloc(sizeof (Emotion_Webcam)); + if (!test) return NULL; + + test->custom = NULL; + test->syspath = eina_stringshare_ref(syspath); + test->name = eeze_udev_syspath_get_sysattr(syspath, "name"); + + device = eeze_udev_syspath_get_property(syspath, "DEVNAME"); + local = alloca(eina_stringshare_strlen(device) + 8); + snprintf(local, eina_stringshare_strlen(device) + 8, "v4l2://%s", device); + test->device = eina_stringshare_add(local); + eina_stringshare_del(device); + test->filename = test->device + 7; + + return test; +} + +static void +_emotion_enumerate_all_webcams(void) +{ + Eina_List *devices; + const char *syspath; + + devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_V4L, NULL); + + EINA_LIST_FREE(devices, syspath) + { + Emotion_Webcam *test; + + test = _emotion_webcam_new(syspath); + if (test) _emotion_check_device(test); + + eina_stringshare_del(syspath); + } +} + +static void +_emotion_eeze_events(const char *syspath, + Eeze_Udev_Event ev, + void *data __UNUSED__, + Eeze_Udev_Watch *watcher __UNUSED__) +{ + if (ev == EEZE_UDEV_EVENT_REMOVE) + { + Emotion_Webcam *check; + Eina_List *l; + + EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check) + if (check->syspath == syspath) + { + _emotion_webcams->webcams = eina_list_remove_list(_emotion_webcams->webcams, l); + EINA_REFCOUNT_UNREF(check) + emotion_webcam_destroy(check); + break ; + } + } + else if (ev == EEZE_UDEV_EVENT_ADD) + { + Emotion_Webcam *test; + + test = _emotion_webcam_new(syspath); + if (test) _emotion_check_device(test); + } + ecore_event_add(EMOTION_WEBCAM_UPDATE, NULL, NULL, NULL); +} + +#endif + +EAPI Eina_Bool +emotion_init(void) +{ + char buffer[4096]; + + if (_emotion_webcams_count++) return EINA_TRUE; + + ecore_init(); + + snprintf(buffer, 4096, "%s/emotion.cfg", PACKAGE_DATA_DIR); + _emotion_webcams_file = eet_open(buffer, EET_FILE_MODE_READ); + if (_emotion_webcams_file) + { + Eet_Data_Descriptor *edd; + + edd = _emotion_webcams_data(); + + _emotion_webcams = eet_data_read(_emotion_webcams_file, edd, "config"); + + eet_data_descriptor_free(_webcams_edd); _webcams_edd = NULL; + eet_data_descriptor_free(_webcam_edd); _webcam_edd = NULL; + } + + if (!_emotion_webcams) + { + _emotion_webcams = calloc(1, sizeof (Emotion_Webcams)); + if (!_emotion_webcams) return EINA_FALSE; + } + +#ifdef EMOTION_HAVE_EEZE + EMOTION_WEBCAM_UPDATE = ecore_event_type_new(); + + eeze_init(); + + _emotion_enumerate_all_webcams(); + + eeze_watcher = eeze_udev_watch_add(EEZE_UDEV_TYPE_V4L, + (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE), + _emotion_eeze_events, NULL); +#endif + + return EINA_TRUE; +} + +EAPI Eina_Bool +emotion_shutdown(void) +{ + Emotion_Webcam *ew; + double start; + + if (_emotion_webcams_count <= 0) + { + EINA_LOG_ERR("Init count not greater than 0 in shutdown."); + return EINA_FALSE; + } + if (--_emotion_webcams_count) return EINA_TRUE; + + EINA_LIST_FREE(_emotion_webcams->webcams, ew) + { +#ifdef EMOTION_HAVE_EEZE + /* There is currently no way to refcount from the outside, this help, but could lead to some issue */ + EINA_REFCOUNT_UNREF(ew) + emotion_webcam_destroy(ew); +#endif + } + free(_emotion_webcams); + _emotion_webcams = NULL; + + if (_emotion_webcams_file) + { + /* As long as there is no one reference any pointer, you are safe */ + eet_close(_emotion_webcams_file); + _emotion_webcams_file = NULL; + } + +#ifdef EMOTION_HAVE_EEZE + eeze_udev_watch_del(eeze_watcher); + eeze_watcher = NULL; + + eeze_shutdown(); +#endif + + start = ecore_time_get(); + while (emotion_pending_objects && ecore_time_get() - start < 0.5) + ecore_main_loop_iterate(); + + if (emotion_pending_objects) + { + EINA_LOG_ERR("There is still %i Emotion pipeline running", emotion_pending_objects); + } + + ecore_shutdown(); + + return EINA_TRUE; +} + +EAPI const Eina_List * +emotion_webcams_get(void) +{ + return _emotion_webcams->webcams; +} + +EAPI const char * +emotion_webcam_name_get(const Emotion_Webcam *ew) +{ + if (!ew) return NULL; + + return ew->name; +} + +EAPI const char * +emotion_webcam_device_get(const Emotion_Webcam *ew) +{ + if (!ew) return NULL; + + return ew->device; +} + +EAPI const char * +emotion_webcam_custom_get(const char *device) +{ + const Emotion_Webcam *ew; + const Eina_List *l; + + if (_emotion_webcams) + { + EINA_LIST_FOREACH(_emotion_webcams->webcams, l, ew) + if (ew->device && strcmp(device, ew->device) == 0) + return ew->custom; + } + + return NULL; +} + +EAPI void +_emotion_pending_object_ref(void) +{ + emotion_pending_objects++; +} + +EAPI void +_emotion_pending_object_unref(void) +{ + emotion_pending_objects--; +} diff --git a/src/lib/emotion_private.h b/src/lib/emotion_private.h index 4d92561..cf24c75 100644 --- a/src/lib/emotion_private.h +++ b/src/lib/emotion_private.h @@ -1,18 +1,6 @@ #ifndef EMOTION_PRIVATE_H #define EMOTION_PRIVATE_H -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "config.h" - #define META_TRACK_TITLE 1 #define META_TRACK_ARTIST 2 #define META_TRACK_GENRE 3 @@ -23,9 +11,12 @@ #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 { @@ -36,32 +27,17 @@ 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 @@ -74,13 +50,15 @@ 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); @@ -121,23 +99,37 @@ struct _Emotion_Video_Module 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 diff --git a/src/lib/emotion_smart.c b/src/lib/emotion_smart.c index 5943820..48eafda 100644 --- a/src/lib/emotion_smart.c +++ b/src/lib/emotion_smart.c @@ -1,6 +1,24 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#ifdef HAVE_EIO +# include +# include +#endif + #include "Emotion.h" #include "emotion_private.h" +#ifdef _WIN32 +# define FMT_UCHAR "%c" +#else +# define FMT_UCHAR "%hhu" +#endif + #define E_SMART_OBJ_GET(smart, o, type) \ { \ char *_e_smart_str; \ @@ -25,30 +43,37 @@ 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; @@ -61,8 +86,39 @@ struct _Smart_Data 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); @@ -85,75 +141,208 @@ static void _smart_clip_unset(Evas_Object * obj); /* 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); } } @@ -170,6 +359,16 @@ emotion_object_add(Evas *evas) 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) { @@ -177,93 +376,121 @@ emotion_object_module_option_set(Evas_Object *obj, const char *opt, const char * 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; @@ -271,27 +498,242 @@ emotion_object_file_get(Evas_Object *obj) 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; } @@ -302,8 +744,15 @@ emotion_object_position_set(Evas_Object *obj, double sec) Smart_Data *sd; E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("sec=%f", sec); if (!sd->module) return; - if (!sd->video) 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; @@ -312,74 +761,89 @@ emotion_object_position_set(Evas_Object *obj, double sec) } 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; @@ -387,8 +851,8 @@ emotion_object_smooth_scale_set(Evas_Object *obj, Evas_Bool smooth) 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; @@ -397,16 +861,19 @@ emotion_object_smooth_scale_get(Evas_Object *obj) } 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) { @@ -414,8 +881,8 @@ 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 @@ -424,64 +891,66 @@ emotion_object_audio_volume_set(Evas_Object *obj, double vol) Smart_Data *sd; E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("vol=%f", vol); if (!sd->module) return; - if (!sd->video) 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 @@ -490,64 +959,66 @@ emotion_object_audio_channel_set(Evas_Object *obj, int channel) Smart_Data *sd; E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("channel=%d", channel); if (!sd->module) return; - if (!sd->video) 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 @@ -556,64 +1027,66 @@ emotion_object_video_channel_set(Evas_Object *obj, int channel) Smart_Data *sd; E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("channel=%d", channel); if (!sd->module) return; - if (!sd->video) 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 @@ -622,31 +1095,32 @@ emotion_object_spu_channel_set(Evas_Object *obj, int channel) Smart_Data *sd; E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("channel=%d", channel); if (!sd->module) return; - if (!sd->video) 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 @@ -655,31 +1129,32 @@ emotion_object_chapter_set(Evas_Object *obj, int chapter) Smart_Data *sd; E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("chapter=%d", chapter); if (!sd->module) return; - if (!sd->video) 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 @@ -688,20 +1163,21 @@ emotion_object_play_speed_set(Evas_Object *obj, double speed) Smart_Data *sd; E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + DBG("speed=%f", speed); if (!sd->module) return; - if (!sd->video) 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 @@ -711,12 +1187,12 @@ emotion_object_eject(Evas_Object *obj) 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; @@ -725,7 +1201,7 @@ emotion_object_title_get(Evas_Object *obj) } EAPI const char * -emotion_object_progress_info_get(Evas_Object *obj) +emotion_object_progress_info_get(const Evas_Object *obj) { Smart_Data *sd; @@ -734,7 +1210,7 @@ emotion_object_progress_info_get(Evas_Object *obj) } EAPI double -emotion_object_progress_status_get(Evas_Object *obj) +emotion_object_progress_status_get(const Evas_Object *obj) { Smart_Data *sd; @@ -743,7 +1219,7 @@ emotion_object_progress_status_get(Evas_Object *obj) } EAPI const char * -emotion_object_ref_file_get(Evas_Object *obj) +emotion_object_ref_file_get(const Evas_Object *obj) { Smart_Data *sd; @@ -752,7 +1228,7 @@ emotion_object_ref_file_get(Evas_Object *obj) } EAPI int -emotion_object_ref_num_get(Evas_Object *obj) +emotion_object_ref_num_get(const Evas_Object *obj) { Smart_Data *sd; @@ -761,7 +1237,7 @@ emotion_object_ref_num_get(Evas_Object *obj) } EAPI int -emotion_object_spu_button_count_get(Evas_Object *obj) +emotion_object_spu_button_count_get(const Evas_Object *obj) { Smart_Data *sd; @@ -770,7 +1246,7 @@ emotion_object_spu_button_count_get(Evas_Object *obj) } EAPI int -emotion_object_spu_button_get(Evas_Object *obj) +emotion_object_spu_button_get(const Evas_Object *obj) { Smart_Data *sd; @@ -779,58 +1255,291 @@ emotion_object_spu_button_get(Evas_Object *obj) } 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 @@ -839,9 +1548,8 @@ _emotion_frame_new(Evas_Object *obj) 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 @@ -855,32 +1563,49 @@ _emotion_video_pos_update(Evas_Object *obj, double pos, double len) 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 @@ -892,20 +1617,41 @@ _emotion_decode_stop(Evas_Object *obj) 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 @@ -914,7 +1660,7 @@ _emotion_channels_change(Evas_Object *obj) 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 @@ -923,33 +1669,33 @@ _emotion_title_set(Evas_Object *obj, char *title) 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 @@ -959,7 +1705,7 @@ _emotion_spu_button_num_set(Evas_Object *obj, int num) 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 @@ -969,16 +1715,61 @@ _emotion_spu_button_set(Evas_Object *obj, int button) 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; @@ -988,17 +1779,17 @@ _mouse_move(void *data, Evas *ev, Evas_Object *obj, void *event_info) 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; @@ -1008,13 +1799,13 @@ _mouse_down(void *data, Evas *ev, Evas_Object *obj, void *event_info) 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 @@ -1026,9 +1817,11 @@ _pos_set_job(void *data) 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; } } @@ -1043,26 +1836,24 @@ _pixels_get(void *data, Evas_Object *obj) 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; @@ -1071,101 +1862,107 @@ _pixels_get(void *data, Evas_Object *obj) 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); } } @@ -1178,13 +1975,21 @@ _smart_add(Evas_Object * obj) 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) @@ -1193,6 +1998,8 @@ _smart_add(Evas_Object * obj) evas_object_image_data_set(obj, pixel); } evas_object_smart_data_set(obj, sd); + + ecore_init(); } static void @@ -1202,26 +2009,22 @@ _smart_del(Evas_Object * obj) 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 @@ -1231,19 +2034,26 @@ _smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h) 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 @@ -1254,6 +2064,9 @@ _smart_hide(Evas_Object * obj) 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 @@ -1264,6 +2077,7 @@ _smart_color_set(Evas_Object * obj, int r, int g, int b, int a) 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 @@ -1273,7 +2087,11 @@ _smart_clip_set(Evas_Object * obj, Evas_Object * clip) 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 @@ -1283,5 +2101,10 @@ _smart_clip_unset(Evas_Object * obj) 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); } + diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am index 1af8c8c..faaa146 100644 --- a/src/modules/Makefile.am +++ b/src/modules/Makefile.am @@ -1,4 +1,4 @@ MAINTAINERCLEANFILES = Makefile.in -SUBDIRS = xine gstreamer +SUBDIRS = xine gstreamer generic diff --git a/src/modules/generic/Emotion_Generic_Plugin.h b/src/modules/generic/Emotion_Generic_Plugin.h new file mode 100644 index 0000000..17bd7e9 --- /dev/null +++ b/src/modules/generic/Emotion_Generic_Plugin.h @@ -0,0 +1,144 @@ +#ifndef EMOTION_GENERIC_PLUGIN_H +#define EMOTION_GENERIC_PLUGIN_H + +#include +#include +#include +#include +#include + +#include + +#define DEFAULTWIDTH 320 +#define DEFAULTHEIGHT 240 +#define DEFAULTPITCH 4 + +typedef enum _Emotion_Generic_Cmd Emotion_Generic_Cmd; +typedef enum _Emotion_Generic_Result Emotion_Generic_Result; +typedef struct _Emotion_Generic_Video_Frame Emotion_Generic_Video_Frame; +typedef struct _Emotion_Generic_Video_Shared Emotion_Generic_Video_Shared; + +enum _Emotion_Generic_Cmd +{ + EM_CMD_INIT = 0, // param: shared memory identifier (string) + EM_CMD_PLAY, // param: position (float) + EM_CMD_STOP, // param: none + EM_CMD_FILE_SET, // param: filename (string) + EM_CMD_FILE_SET_DONE, // param: success (int) + EM_CMD_FILE_CLOSE, // param: none + EM_CMD_POSITION_SET, // param: position (float) + EM_CMD_SPEED_SET, // param: speed (float) + EM_CMD_AUDIO_MUTE_SET, // param: muted (int) + EM_CMD_VIDEO_MUTE_SET, // param: muted (int) + EM_CMD_SPU_MUTE_SET, // param: muted (int) + EM_CMD_VOLUME_SET, // param: volume (float) + EM_CMD_AUDIO_TRACK_SET, // param: track id (int) + EM_CMD_VIDEO_TRACK_SET, // param: track id (int) + EM_CMD_SPU_TRACK_SET, // param: track id (int) + EM_CMD_LAST +}; + +enum _Emotion_Generic_Result +{ + EM_RESULT_INIT = 0, // param: none + EM_RESULT_FILE_SET, // param: none + EM_RESULT_FILE_SET_DONE, // param: success (int) + EM_RESULT_PLAYBACK_STARTED, // param: none + EM_RESULT_PLAYBACK_STOPPED, // param: none + EM_RESULT_FILE_CLOSE, // param: none + EM_RESULT_FRAME_NEW, // param: none + EM_RESULT_FRAME_SIZE, // param: int, int (width, height) + EM_RESULT_LENGTH_CHANGED, // param: float + EM_RESULT_POSITION_CHANGED, // param: float + EM_RESULT_SEEKABLE_CHANGED, // param: int + EM_RESULT_AUDIO_TRACK_INFO, // param: current track, track count, track_id, track_name, track_id2, track_name2, ... + EM_RESULT_VIDEO_TRACK_INFO, // param: current track, track count, track_id, track_name, track_id2, track_name2, ... + EM_RESULT_SPU_TRACK_INFO, // param: current spu, spu count, spu_id, spu_name, spu_id2, spu_name2, ... + // (int, int, int, string, int, string, ...) + EM_RESULT_META_INFO, // param: title, artist, album, year, genre, comments, disc id, count (all int) + EM_RESULT_LAST +}; + +/* structure for frames 2 buffers to keep integrity */ +struct _Emotion_Generic_Video_Frame +{ + unsigned char *frames[3]; +}; + +/* structure for frames 2 buffers to keep integrity */ +struct _Emotion_Generic_Video_Shared +{ + int size; + int width; + int height; + int pitch; + /** + * - "emotion" is the frame from where the Emotion process is reading pixels. + * The player shouldn't touch this frame. + * - "player" is the frame where the slayer process is writing pixels. + * The emotion process shouldn't touch this frame. + * - "last" is the last frame that was rendered by the player. Emotion will + * use this frame the next time it will fetch pixels to Evas. + * - "next" is the unused frame. The player currently using the "player" + * should, after finishing this frame, set "last" to "player", and "player" + * to "next", and finally "next" to "last" so this operation can be done + * many times in case that Emotion does not request pixels fast enough. + */ + struct { + int emotion; + int player; + int last; + int next; + } frame; + Eina_Semaphore lock; + int frame_drop; +}; + +static inline int +emotion_generic_shm_get(const char *shmname, Emotion_Generic_Video_Shared **vs, Emotion_Generic_Video_Frame *vf) +{ + int shmfd = -1; + int size; + Emotion_Generic_Video_Shared *t_vs; + + shmfd = shm_open(shmname, O_RDWR, 0777); + if (shmfd == -1) + { + fprintf(stderr, "player: could not open shm: %s\n", shmname); + fprintf(stderr, "player: %s\n", strerror(errno)); + return 0; + } + + t_vs = mmap(NULL, sizeof(*t_vs), PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0); + if (t_vs == MAP_FAILED) + { + fprintf(stderr, "player: could not map shared memory.\n"); + fprintf(stderr, "player: %s\n", strerror(errno)); + return 0; + } + size = t_vs->size; + munmap(t_vs, sizeof(*t_vs)); + t_vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0); + if (t_vs == MAP_FAILED) + { + fprintf(stderr, "player: could not map shared memory.\n"); + fprintf(stderr, "player: %s\n", strerror(errno)); + return 0; + } + + vf->frames[0] = (unsigned char *)t_vs + sizeof(*t_vs); + vf->frames[1] = (unsigned char *)t_vs + sizeof(*t_vs) + t_vs->height * t_vs->width * t_vs->pitch; + vf->frames[2] = (unsigned char *)t_vs + sizeof(*t_vs) + 2 * t_vs->height * t_vs->width * t_vs->pitch; + + *vs = t_vs; + + return 1; +} + +static inline void +emotion_generic_shm_free(Emotion_Generic_Video_Shared *vs) +{ + munmap(vs, vs->size); +} + +#endif // EMOTION_GENERIC_PLUGIN_H diff --git a/src/modules/generic/Makefile.am b/src/modules/generic/Makefile.am new file mode 100644 index 0000000..23be987 --- /dev/null +++ b/src/modules/generic/Makefile.am @@ -0,0 +1,31 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/modules \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EMOTION_CFLAGS@ \ +@EMOTION_CPPFLAGS@ \ +@EFL_EMOTION_BUILD@ + +if EMOTION_BUILD_GENERIC +if !EMOTION_STATIC_BUILD_GENERIC + +pkgdir = $(libdir)/emotion + +pkg_LTLIBRARIES = em_generic.la +includes_HEADERS = Emotion_Generic_Plugin.h +includesdir = $(includedir)/emotion-@VMAJ@ +noinst_HEADERS = emotion_generic.h + +em_generic_la_SOURCES = emotion_generic.c +em_generic_la_LIBADD = @EMOTION_LIBS@ @EFL_SHM_OPEN_LIBS@ $(top_builddir)/src/lib/libemotion.la +em_generic_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +em_generic_la_LIBTOOLFLAGS = --tag=disable-static +em_generic_la_DEPENDENCIES = emotion_generic.h Emotion_Generic_Plugin.h + +endif +endif diff --git a/src/modules/generic/README b/src/modules/generic/README new file mode 100644 index 0000000..c2a028d --- /dev/null +++ b/src/modules/generic/README @@ -0,0 +1,79 @@ +Generic - emotion backend +========================= + +This generic player backend executes a separate player in another +process. It receives the bytes to be drawn on the emotion object through +a shared memory, and communicates with the player through a pipe, using +the player standard input/output. + +The player must communicate with emotion using the defined commands +specified in the Emotion_Generic_Plugin.h. It doesn't need to link +against emotion, just include this file for easier implementation. + + +How does it work? +================= + +When the module is initialized for an emotion object, it starts another process +that runs the specified player. The player command line is specified using: + + emotion_object_module_option_set(object, "player", ); + +A player using libvlc is being provided now, and the generic module internally +checks if the command given was "vlc", in which case it will use this provided +vlc player. + +When a file is set to this object, it will send the file name to the player, and +expect an answer that will tell that the player already decoded a bit of the +file, and the video size is already set on the module, so it can allocate a +shared memory with correct size. + +The module then allocates the memory, sends a message to the player and expect +an answer. After this last answer, the "open_done" signal is sent and the module +knows that it is ready for playing. Commands sent before the module being ready +are now applied (and play is resumed if necessary). + +During this setup stage, info about the file set will be stored in the module, +so commands like meta data get, length get and so will be available to sync +calls like emotion_object_play_length_get(); + +If the player dies for any reason, a "decode_stop" signal is sent (should change +to something more like an error signal), and if play is called again, it will be +restarted. The playback should start from the same point it was before the +player crashed, if the player supports seek on the current media format). + +TODO +==== + + - Provide better description for commands; + - Explain in details the communication emotion <-> player; + - Make more common functions for players; + - (maybe) add support for named pipes, so we don't rely on standard in/out + for communication; + - Add a detection on the player to know that the emotion process died (so it + can just exit); + - shmname should contain the child pid too; + - better names for commands, maybe add namespace everywhere; + + +questions +========= + + - Using semaphores to lock the critical region between process, and pthread + mutexes for the threads inside the player. Should move to only one type + (semphores or mutexes)? + - There are 2 inline functions insde Emotion_Generic_Plugin.h to make it easier + for the player to get the shared memory correctly. Any problem with this? + Would be good to add more functions/macros to make common tasks like + parsing commands there too? + - Should move players to another project (outside of emotion)? + + +problems +======== + - file_set has some critical time when file is not set yet when we can't call + some functions (I think only another file_set now); + - communication player -> emotion depends on '\n' to delimitate commands, will + remove this soon (fix this urgently!); + - need to implement missing APIs; + diff --git a/src/modules/generic/emotion_generic.c b/src/modules/generic/emotion_generic.c new file mode 100644 index 0000000..e4771ce --- /dev/null +++ b/src/modules/generic/emotion_generic.c @@ -0,0 +1,1794 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Emotion.h" +#include "emotion_private.h" +#include "emotion_generic.h" + +static Eina_Prefix *pfx = NULL; + +static int _emotion_generic_log_domain = -1; +#define DBG(...) EINA_LOG_DOM_DBG(_emotion_generic_log_domain, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(_emotion_generic_log_domain, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(_emotion_generic_log_domain, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(_emotion_generic_log_domain, __VA_ARGS__) +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_emotion_generic_log_domain, __VA_ARGS__) + + +struct _default_players { + const char *name; + const char *cmdline; +}; + +static struct _default_players players[] = { +#ifdef EMOTION_BUILD_GENERIC_VLC + { "vlc", "em_generic_vlc" }, +#endif + { NULL, NULL } +}; + +static Eina_Bool _fork_and_exec(Emotion_Generic_Video *ev); +static void em_partial_shutdown(Emotion_Generic_Video *ev); + +static Eina_Bool +_player_restart(void *data) +{ + Emotion_Generic_Video *ev = data; + + _fork_and_exec(ev); + ev->player_restart = NULL; + return EINA_FALSE; +} + +static const char * +_get_player(const char *name) +{ + const char *selected_name = NULL; + const char *libdir = eina_prefix_lib_get(pfx); + static char buf[PATH_MAX]; + int i; + + if (name) + { + for (i = 0; players[i].name; i++) + { + if (!strcmp(players[i].name, name)) + { + selected_name = players[i].cmdline; + break; + } + } + } + + if ((!selected_name) && (name)) + selected_name = name; + + if (selected_name) + { + const char *cmd; + + if (selected_name[0] == '/') cmd = selected_name; + else + { + snprintf(buf, sizeof(buf), "%s/emotion/utils/%s", + libdir, selected_name); + cmd = buf; + } + + DBG("Try generic player '%s'", cmd); + if (access(cmd, R_OK | X_OK) == 0) + { + INF("Using generic player '%s'", cmd); + return cmd; + } + } + + for (i = 0; players[i].name; i++) + { + snprintf(buf, sizeof(buf), "%s/emotion/utils/%s", + libdir, players[i].cmdline); + DBG("Try generic player '%s'", buf); + if (access(buf, R_OK | X_OK) == 0) + { + INF("Using fallback player '%s'", buf); + return buf; + } + } + + ERR("no generic player found, given name='%s'", name ? name : ""); + return NULL; +} + +static void +_player_send_cmd(Emotion_Generic_Video *ev, int cmd) +{ + if (cmd >= EM_CMD_LAST) + { + ERR("invalid command to player."); + return; + } + if (ev->fd_write == -1) + { + ERR("you should wait for emotion to be ready to take action."); + return ; + } + if (write(ev->fd_write, &cmd, sizeof(cmd)) < 0) perror("write"); +} + +static void +_player_send_int(Emotion_Generic_Video *ev, int number) +{ + if (ev->fd_write == -1) + { + ERR("you should wait for emotion to be ready to take action."); + return ; + } + if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write"); +} + +static void +_player_send_float(Emotion_Generic_Video *ev, float number) +{ + if (ev->fd_write == -1) + { + ERR("you should wait for emotion to be ready to take action."); + return ; + } + if (write(ev->fd_write, &number, sizeof(number)) < 0) perror("write"); +} + +static void +_player_send_str(Emotion_Generic_Video *ev, const char *str, Eina_Bool stringshared) +{ + int len; + + if (stringshared) + len = eina_stringshare_strlen(str) + 1; + else + len = strlen(str) + 1; + if (write(ev->fd_write, &len, sizeof(len)) < 0) perror("write"); + if (write(ev->fd_write, str, len) < 0) perror("write"); +} + +static Eina_Bool +_create_shm_data(Emotion_Generic_Video *ev, const char *shmname) +{ + int shmfd; + int npages; + size_t size; + Emotion_Generic_Video_Shared *vs; + + shmfd = shm_open(shmname, O_CREAT | O_RDWR | O_TRUNC, 0777); + if (shmfd == -1) + { + ERR("player: could not open shm: %s", shmname); + ERR("player: %s", strerror(errno)); + return 0; + } + size = 3 * (ev->w * ev->h * DEFAULTPITCH) + sizeof(*vs); + + npages = (int)(size / getpagesize()) + 1; + size = npages * getpagesize(); + + if (ftruncate(shmfd, size)) + { + ERR("error when allocating shared memory (size = %zd): " + "%s", size, strerror(errno)); + shm_unlink(shmname); + return EINA_FALSE; + } + vs = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0); + if (vs == MAP_FAILED) + { + ERR("error when mapping shared memory"); + return EINA_FALSE; + } + + vs->size = size; + vs->width = ev->w; + vs->height = ev->h; + vs->pitch = DEFAULTPITCH; + vs->frame.emotion = 0; + vs->frame.player = 1; + vs->frame.last = 2; + vs->frame.next = 2; + vs->frame_drop = 0; + if (!eina_semaphore_new(&vs->lock, 1)) + { + ERR("can not create semaphore"); + return EINA_FALSE; + } + ev->frame.frames[0] = (unsigned char *)vs + sizeof(*vs); + ev->frame.frames[1] = (unsigned char *)vs + sizeof(*vs) + vs->height * vs->width * vs->pitch; + ev->frame.frames[2] = (unsigned char *)vs + sizeof(*vs) + 2 * vs->height * vs->width * vs->pitch; + + if (ev->shared) + munmap(ev->shared, ev->shared->size); + ev->shared = vs; + + return EINA_TRUE; +} + +static void +_player_new_frame(Emotion_Generic_Video *ev) +{ + if (!ev->file_ready) + return; + _emotion_frame_new(ev->obj); +} + +static void +_file_open(Emotion_Generic_Video *ev) +{ + INF("Opening file: %s", ev->filename); + ev->drop = 0; + + if (!ev->ready || !ev->filename) + return; + _player_send_cmd(ev, EM_CMD_FILE_SET); + _player_send_str(ev, ev->filename, EINA_TRUE); +} + +static void +_player_file_set_done(Emotion_Generic_Video *ev) +{ + if (ev->file_changed) + { + _file_open(ev); + ev->file_changed = EINA_FALSE; + return; + } + + if (!_create_shm_data(ev, ev->shmname)) + { + ERR("could not create shared memory."); + return; + } + _player_send_cmd(ev, EM_CMD_FILE_SET_DONE); +} + +static void +_player_ready(Emotion_Generic_Video *ev) +{ + INF("received: player ready."); + + ev->initializing = EINA_FALSE; + ev->ready = EINA_TRUE; + + if (!ev->filename) + return; + + _file_open(ev); +} + +static Eina_Bool +_player_cmd_param_read(Emotion_Generic_Video *ev, void *param, size_t size) +{ + ssize_t done, todo, i; + + /* When a parameter must be read, we cannot make sure it will be entirely + * available. Thus we store the bytes that could be read in a temp buffer, + * and when more data is read we try to complete the buffer and finally use + * the read value. + */ + if (!ev->cmd.tmp) + { + ev->cmd.tmp = malloc(size); + ev->cmd.i = 0; + ev->cmd.total = size; + } + + todo = ev->cmd.total - ev->cmd.i; + i = ev->cmd.i; + done = read(ev->fd_read, &ev->cmd.tmp[i], todo); + + if (done < 0 && errno != EINTR && errno != EAGAIN) + { + if (ev->cmd.tmp) + { + free(ev->cmd.tmp); + ev->cmd.tmp = NULL; + } + ERR("problem when reading parameter from pipe."); + ev->cmd.type = -1; + return EINA_FALSE; + } + + if (done == todo) + { + memcpy(param, ev->cmd.tmp, size); + free(ev->cmd.tmp); + ev->cmd.tmp = NULL; + return EINA_TRUE; + } + + if (done > 0) + ev->cmd.i += done; + + return EINA_FALSE; +} + +static void +_player_frame_resize(Emotion_Generic_Video *ev) +{ + int w, h; + + w = ev->cmd.param.size.width; + h = ev->cmd.param.size.height; + + INF("received frame resize: %dx%d", w, h); + ev->w = w; + ev->h = h; + ev->ratio = (float)w / h; + + if (ev->opening) + return; + + _emotion_frame_resize(ev->obj, ev->w, ev->h, ev->ratio); +} + +static void +_player_length_changed(Emotion_Generic_Video *ev) +{ + float length = ev->cmd.param.f_num; + + INF("received length changed: %0.3f", length); + + ev->len = length; + _emotion_video_pos_update(ev->obj, ev->pos, ev->len); +} + +static void +_player_position_changed(Emotion_Generic_Video *ev) +{ + float position = ev->cmd.param.f_num; + + INF("received position changed: %0.3f", position); + + ev->pos = position; + _emotion_video_pos_update(ev->obj, ev->pos, ev->len); +/* hmmm. no _emotion_progress_set() is for "buffering" progress. + if (ev->len == 0) + return; + + float progress = ev->pos / ev->len; + char buf[16]; + snprintf(buf, sizeof(buf), "%0.1f%%", progress * 100); + + _emotion_progress_set(ev->obj, buf, progress); + */ +} + +static void +_player_seekable_changed(Emotion_Generic_Video *ev) +{ + int seekable = ev->cmd.param.i_num; + + INF("received seekable changed: %d", seekable); + + seekable = !!seekable; + + ev->seekable = seekable; +} + +static void +_audio_channels_free(Emotion_Generic_Video *ev) +{ + int i; + for (i = 0; i < ev->audio_channels_count; i++) + eina_stringshare_del(ev->audio_channels[i].name); + free(ev->audio_channels); + ev->audio_channels = NULL; + ev->audio_channels_count = 0; +} + +static void +_video_channels_free(Emotion_Generic_Video *ev) +{ + int i; + for (i = 0; i < ev->video_channels_count; i++) + eina_stringshare_del(ev->video_channels[i].name); + free(ev->video_channels); + ev->video_channels = NULL; + ev->video_channels_count = 0; +} + +static void +_spu_channels_free(Emotion_Generic_Video *ev) +{ + int i; + for (i = 0; i < ev->spu_channels_count; i++) + eina_stringshare_del(ev->spu_channels[i].name); + free(ev->spu_channels); + ev->spu_channels = NULL; + ev->spu_channels_count = 0; +} + +static void +_player_tracks_info(Emotion_Generic_Video *ev, Emotion_Generic_Channel **channels, int *count, int *current) +{ + Emotion_Generic_Channel *pchannels; + int i; + + *count = ev->cmd.param.track.total; + *current = ev->cmd.param.track.current; + pchannels = ev->cmd.param.track.channels; + + INF("number of tracks: %d (current = %d):", *count, *current); + for (i = 0; i < *count; i++) + { + INF("\tchannel %d: %s", pchannels[i].id, pchannels[i].name); + } + + *channels = pchannels; +} + +static void +_player_audio_tracks_info(Emotion_Generic_Video *ev) +{ + INF("Receiving audio channels:"); + if (ev->audio_channels_count) + _audio_channels_free(ev); + + _player_tracks_info(ev, &ev->audio_channels, &ev->audio_channels_count, + &ev->audio_channel_current); +} + +static void +_player_video_tracks_info(Emotion_Generic_Video *ev) +{ + INF("Receiving video channels:"); + if (ev->video_channels_count) + _video_channels_free(ev); + + _player_tracks_info(ev, &ev->video_channels, &ev->video_channels_count, + &ev->video_channel_current); +} + +static void +_player_spu_tracks_info(Emotion_Generic_Video *ev) +{ + INF("Receiving spu channels:"); + if (ev->spu_channels_count) + _spu_channels_free(ev); + + _player_tracks_info(ev, &ev->spu_channels, &ev->spu_channels_count, + &ev->spu_channel_current); +} + +static void +_player_meta_info_free(Emotion_Generic_Video *ev) +{ + eina_stringshare_replace(&ev->meta.title, NULL); + eina_stringshare_replace(&ev->meta.artist, NULL); + eina_stringshare_replace(&ev->meta.album, NULL); + eina_stringshare_replace(&ev->meta.year, NULL); + eina_stringshare_replace(&ev->meta.genre, NULL); + eina_stringshare_replace(&ev->meta.comment, NULL); + eina_stringshare_replace(&ev->meta.disc_id, NULL); + eina_stringshare_replace(&ev->meta.count, NULL); +} + +static void +_player_meta_info_read(Emotion_Generic_Video *ev) +{ + INF("Receiving meta info:"); + _player_meta_info_free(ev); + ev->meta.title = ev->cmd.param.meta.title; + ev->meta.artist = ev->cmd.param.meta.artist; + ev->meta.album = ev->cmd.param.meta.album; + ev->meta.year = ev->cmd.param.meta.year; + ev->meta.genre = ev->cmd.param.meta.genre; + ev->meta.comment = ev->cmd.param.meta.comment; + ev->meta.disc_id = ev->cmd.param.meta.disc_id; + ev->meta.count = ev->cmd.param.meta.count; + INF("title: '%s'", ev->meta.title); + INF("artist: '%s'", ev->meta.artist); + INF("album: '%s'", ev->meta.album); + INF("year: '%s'", ev->meta.year); + INF("genre: '%s'", ev->meta.genre); + INF("comment: '%s'", ev->meta.comment); + INF("disc_id: '%s'", ev->meta.disc_id); + INF("count: '%s'", ev->meta.count); +} + +static void +_player_file_closed(Emotion_Generic_Video *ev) +{ + INF("Closed previous file."); + eina_semaphore_free(&ev->shared->lock); + ev->closing = EINA_FALSE; + + if (ev->opening) + _file_open(ev); +} + +static void +_player_open_done(Emotion_Generic_Video *ev) +{ + int success; + + success = ev->cmd.param.i_num; + shm_unlink(ev->shmname); + + if (ev->file_changed) + { + _file_open(ev); + ev->file_changed = EINA_FALSE; + return; + } + + ev->opening = EINA_FALSE; + if (!success) + { + ERR("Could not open file."); + return; + } + + ev->file_ready = EINA_TRUE; + + _emotion_open_done(ev->obj); + + if (ev->play) + { + _player_send_cmd(ev, EM_CMD_PLAY); + _player_send_float(ev, ev->pos); + } + + _player_send_cmd(ev, EM_CMD_VOLUME_SET); + _player_send_float(ev, ev->volume); + + _player_send_cmd(ev, EM_CMD_SPEED_SET); + _player_send_float(ev, ev->speed); + + int mute = ev->audio_mute; + _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET); + _player_send_int(ev, mute); + + mute = ev->video_mute; + _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET); + _player_send_int(ev, mute); + + mute = ev->spu_mute; + _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET); + _player_send_int(ev, mute); + + INF("Open done"); +} + +static void +_player_cmd_process(Emotion_Generic_Video *ev) +{ + switch (ev->cmd.type) { + case EM_RESULT_INIT: + _player_ready(ev); + break; + case EM_RESULT_FRAME_NEW: + _player_new_frame(ev); + break; + case EM_RESULT_FILE_SET: + _player_file_set_done(ev); + break; + case EM_RESULT_FILE_SET_DONE: + _player_open_done(ev); + break; + case EM_RESULT_FILE_CLOSE: + _player_file_closed(ev); + break; + case EM_RESULT_PLAYBACK_STARTED: + _emotion_playback_started(ev->obj); + break; + case EM_RESULT_PLAYBACK_STOPPED: + ev->pos = 0; + _emotion_playback_finished(ev->obj); + _emotion_decode_stop(ev->obj); + + em_partial_shutdown(ev); + ev->player_restart = ecore_idler_add(_player_restart, ev); + break; + case EM_RESULT_FRAME_SIZE: + _player_frame_resize(ev); + break; + case EM_RESULT_LENGTH_CHANGED: + _player_length_changed(ev); + break; + case EM_RESULT_POSITION_CHANGED: + _player_position_changed(ev); + break; + case EM_RESULT_SEEKABLE_CHANGED: + _player_seekable_changed(ev); + break; + case EM_RESULT_AUDIO_TRACK_INFO: + _player_audio_tracks_info(ev); + break; + case EM_RESULT_VIDEO_TRACK_INFO: + _player_video_tracks_info(ev); + break; + case EM_RESULT_SPU_TRACK_INFO: + _player_spu_tracks_info(ev); + break; + case EM_RESULT_META_INFO: + _player_meta_info_read(ev); + break; + default: + WRN("received wrong command: %d", ev->cmd.type); + } + + ev->cmd.type = -1; +} + +static void +_player_cmd_single_int_process(Emotion_Generic_Video *ev) +{ + if (!_player_cmd_param_read(ev, &ev->cmd.param.i_num, sizeof(ev->cmd.param.i_num))) + return; + + _player_cmd_process(ev); +} + +static void +_player_cmd_single_float_process(Emotion_Generic_Video *ev) +{ + if (!_player_cmd_param_read(ev, &ev->cmd.param.f_num, sizeof(ev->cmd.param.f_num))) + return; + + _player_cmd_process(ev); +} + +static void +_player_cmd_double_int_process(Emotion_Generic_Video *ev) +{ + int param; + + if (ev->cmd.num_params == 0) + { + ev->cmd.num_params = 2; + ev->cmd.cur_param = 0; + ev->cmd.param.size.width = 0; + ev->cmd.param.size.height = 0; + } + + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + + if (ev->cmd.cur_param == 0) + ev->cmd.param.size.width = param; + else + ev->cmd.param.size.height = param; + + ev->cmd.cur_param++; + if (ev->cmd.cur_param == ev->cmd.num_params) + _player_cmd_process(ev); +} + +static void +_player_cmd_track_info(Emotion_Generic_Video *ev) +{ + int param; + int i; + + if (ev->cmd.num_params == 0) + { + ev->cmd.cur_param = 0; + ev->cmd.num_params = 2; + ev->cmd.param.track.channels = NULL; + ev->cmd.s_len = -1; + } + + while (ev->cmd.cur_param < 2) + { + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + + if (ev->cmd.cur_param == 0) + ev->cmd.param.track.current = param; + else + { + ev->cmd.param.track.total = param; + ev->cmd.num_params += param * 2; + ev->cmd.param.track.channels = + calloc(param, sizeof(*ev->cmd.param.track.channels)); + } + ev->cmd.cur_param++; + } + + if (ev->cmd.cur_param == ev->cmd.num_params) + { + _player_cmd_process(ev); + return; + } + + i = (ev->cmd.cur_param - 2) / 2; + if ((ev->cmd.cur_param % 2) == 0) // reading track id + { + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + ev->cmd.param.track.channels[i].id = param; + ev->cmd.cur_param++; + } + else // reading track name + { + char buf[PATH_MAX]; + + if (ev->cmd.s_len == -1) + { + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + ev->cmd.s_len = param; + } + + if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len)) + return; + ev->cmd.param.track.channels[i].name = + eina_stringshare_add_length(buf, ev->cmd.s_len); + ev->cmd.cur_param++; + ev->cmd.s_len = -1; + } + + if (ev->cmd.cur_param == ev->cmd.num_params) + _player_cmd_process(ev); +} + +static void +_player_cmd_meta_info(Emotion_Generic_Video *ev) +{ + int param; + const char *info; + char buf[PATH_MAX]; + + if (ev->cmd.num_params == 0) + { + ev->cmd.cur_param = 0; + ev->cmd.num_params = 8; + ev->cmd.param.meta.title = NULL; + ev->cmd.param.meta.artist = NULL; + ev->cmd.param.meta.album = NULL; + ev->cmd.param.meta.year = NULL; + ev->cmd.param.meta.genre = NULL; + ev->cmd.param.meta.comment = NULL; + ev->cmd.param.meta.disc_id = NULL; + ev->cmd.param.meta.count = NULL; + ev->cmd.s_len = -1; + } + + if (ev->cmd.s_len == -1) + { + if (!_player_cmd_param_read(ev, ¶m, sizeof(param))) + return; + ev->cmd.s_len = param; + } + + if (!_player_cmd_param_read(ev, buf, ev->cmd.s_len)) + return; + + info = eina_stringshare_add_length(buf, ev->cmd.s_len); + ev->cmd.s_len = -1; + + if (ev->cmd.cur_param == 0) + ev->cmd.param.meta.title = info; + else if (ev->cmd.cur_param == 1) + ev->cmd.param.meta.artist = info; + else if (ev->cmd.cur_param == 2) + ev->cmd.param.meta.album = info; + else if (ev->cmd.cur_param == 3) + ev->cmd.param.meta.year = info; + else if (ev->cmd.cur_param == 4) + ev->cmd.param.meta.genre = info; + else if (ev->cmd.cur_param == 5) + ev->cmd.param.meta.comment = info; + else if (ev->cmd.cur_param == 6) + ev->cmd.param.meta.disc_id = info; + else if (ev->cmd.cur_param == 7) + ev->cmd.param.meta.count = info; + + ev->cmd.cur_param++; + + if (ev->cmd.cur_param == 8) + _player_cmd_process(ev); +} + +static void +_player_cmd_read(Emotion_Generic_Video *ev) +{ + if (ev->cmd.type < 0) + { + if (!_player_cmd_param_read(ev, &ev->cmd.type, sizeof(ev->cmd.type))) + return; + ev->cmd.num_params = 0; + } + + switch (ev->cmd.type) { + case EM_RESULT_INIT: + case EM_RESULT_FILE_SET: + case EM_RESULT_PLAYBACK_STARTED: + case EM_RESULT_PLAYBACK_STOPPED: + case EM_RESULT_FILE_CLOSE: + case EM_RESULT_FRAME_NEW: + _player_cmd_process(ev); + break; + case EM_RESULT_FILE_SET_DONE: + case EM_RESULT_SEEKABLE_CHANGED: + _player_cmd_single_int_process(ev); + break; + case EM_RESULT_LENGTH_CHANGED: + case EM_RESULT_POSITION_CHANGED: + _player_cmd_single_float_process(ev); + break; + case EM_RESULT_FRAME_SIZE: + _player_cmd_double_int_process(ev); + break; + case EM_RESULT_AUDIO_TRACK_INFO: + case EM_RESULT_VIDEO_TRACK_INFO: + case EM_RESULT_SPU_TRACK_INFO: + _player_cmd_track_info(ev); + break; + case EM_RESULT_META_INFO: + _player_cmd_meta_info(ev); + break; + + default: + WRN("received wrong command: %d", ev->cmd.type); + ev->cmd.type = -1; + } +} + +static Eina_Bool +_player_cmd_handler_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + Emotion_Generic_Video *ev = data; + + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) + { + ERR("an error occurred on fd_read %d.", ev->fd_read); + return ECORE_CALLBACK_CANCEL; + } + + _player_cmd_read(ev); + + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_player_data_cb(void *data, int type __UNUSED__, void *event) +{ + Ecore_Exe_Event_Data *ev = event; + Emotion_Generic_Video *evideo = data; + int i; + + if (ev->exe != evideo->player.exe) + { + INF("slave != ev->exe"); + return ECORE_CALLBACK_PASS_ON; + } + + for (i = 0; ev->lines[i].line; i++) + INF("received input from player: \"%s\"", ev->lines[i].line); + + return ECORE_CALLBACK_DONE; +} + +static Eina_Bool +_player_add_cb(void *data, int type __UNUSED__, void *event) +{ + Ecore_Exe_Event_Add *event_add = event; + Ecore_Exe *player = event_add->exe; + Emotion_Generic_Video *ev = data; + + if (ev->player.exe != player) + { + INF("ev->player != player."); + return ECORE_CALLBACK_PASS_ON; + } + + _player_send_cmd(ev, EM_CMD_INIT); + _player_send_str(ev, ev->shmname, EINA_TRUE); + + return ECORE_CALLBACK_DONE; +} + +static Eina_Bool +_player_del_cb(void *data, int type __UNUSED__, void *event __UNUSED__) +{ + Ecore_Exe_Event_Del *event_del = event; + Ecore_Exe *player = event_del->exe; + Emotion_Generic_Video *ev = data; + + if (ev->player.exe != player) + { + INF("ev->player != player."); + return ECORE_CALLBACK_PASS_ON; + } + + ERR("player died."); + + ev->player.exe = NULL; + ev->ready = EINA_FALSE; + ev->file_ready = EINA_FALSE; + ecore_main_fd_handler_del(ev->fd_handler); + close(ev->fd_read); + close(ev->fd_write); + ev->fd_read = -1; + ev->fd_write = -1; + _emotion_decode_stop(ev->obj); + + return ECORE_CALLBACK_DONE; +} + +static Eina_Bool +_player_exec(Emotion_Generic_Video *ev) +{ + int pipe_out[2]; + int pipe_in[2]; + char buf[PATH_MAX]; + + if (pipe(pipe_out) == -1) + { + ERR("could not create pipe for communication emotion -> player: %s", strerror(errno)); + return EINA_FALSE; + } + + if (pipe(pipe_in) == -1) + { + ERR("could not create pipe for communication player -> emotion: %s", strerror(errno)); + close(pipe_out[0]); + close(pipe_out[1]); + return EINA_FALSE; + } + + snprintf(buf, sizeof(buf), "%s %d %d\n", ev->cmdline, pipe_out[0], pipe_in[1]); + + ev->player.exe = ecore_exe_pipe_run( + buf, + ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE | + ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_NOT_LEADER, + ev); + + INF("created pipe emotion -> player: %d -> %d", pipe_out[1], pipe_out[0]); + INF("created pipe player -> emotion: %d -> %d", pipe_in[1], pipe_in[0]); + + close(pipe_in[1]); + close(pipe_out[0]); + + if (!ev->player.exe) + { + close(pipe_in[0]); + close(pipe_out[1]); + return EINA_FALSE; + } + + ev->fd_read = pipe_in[0]; + ev->fd_write = pipe_out[1]; + + ev->fd_handler = ecore_main_fd_handler_add( + ev->fd_read, ECORE_FD_READ | ECORE_FD_ERROR, _player_cmd_handler_cb, ev, + NULL, NULL); + + return EINA_TRUE; +} + +static Eina_Bool +_fork_and_exec(Emotion_Generic_Video *ev) +{ + char shmname[256]; + struct timeval tv; + + gettimeofday(&tv, NULL); + snprintf(shmname, sizeof(shmname), "/em-generic-shm_%d_%d", + (int)tv.tv_sec, (int)tv.tv_usec); + + ev->shmname = eina_stringshare_add(shmname); + + ev->player_add = ecore_event_handler_add( + ECORE_EXE_EVENT_ADD, _player_add_cb, ev); + ev->player_del = ecore_event_handler_add( + ECORE_EXE_EVENT_DEL, _player_del_cb, ev); + ev->player_data = ecore_event_handler_add( + ECORE_EXE_EVENT_DATA, _player_data_cb, ev); + + if (!_player_exec(ev)) + { + ERR("could not start player."); + return EINA_FALSE; + } + + ev->initializing = EINA_TRUE; + + return EINA_TRUE; +} + +static unsigned char +em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt) +{ + Emotion_Generic_Video *ev; + const char *player; + + if (!emotion_video) return 0; + player = _get_player(opt ? opt->player : NULL); + if (!player) return 0; + + ev = (Emotion_Generic_Video *)calloc(1, sizeof(*ev)); + if (!ev) return 0; + + ev->fd_read = -1; + ev->fd_write = -1; + ev->speed = 1.0; + ev->volume = 0.5; + ev->audio_mute = EINA_FALSE; + ev->cmd.type = -1; + + ev->obj = obj; + ev->cmdline = eina_stringshare_add(player); + *emotion_video = ev; + + return _fork_and_exec(ev); +} + +static void +em_partial_shutdown(Emotion_Generic_Video *ev) +{ + _emotion_image_reset(ev->obj); + + if (ev->player.exe) + { + ecore_exe_terminate(ev->player.exe); + ecore_exe_free(ev->player.exe); + ev->player.exe = NULL; + } + + if (ev->shared) + munmap(ev->shared, ev->shared->size); + ev->shared = NULL; + + if (ev->fd_read >= 0) + close(ev->fd_read); + ev->fd_read = -1; + if (ev->fd_write >= 0) + close(ev->fd_write); + ev->fd_write = -1; + if (ev->fd_handler) + ecore_main_fd_handler_del(ev->fd_handler); + ev->fd_handler = NULL; + + if (ev->player_add) ecore_event_handler_del(ev->player_add); + ev->player_add = NULL; + if (ev->player_data) ecore_event_handler_del(ev->player_data); + ev->player_data = NULL; + if (ev->player_del) ecore_event_handler_del(ev->player_del); + ev->player_del = NULL; + if (ev->player_restart) ecore_idler_del(ev->player_restart); + ev->player_restart = NULL; +} + +static int +em_shutdown(void *data) +{ + Emotion_Generic_Video *ev = data; + + if (!ev) return 0; + + eina_stringshare_del(ev->cmdline); + eina_stringshare_del(ev->shmname); + + em_partial_shutdown(ev); + + return 1; +} + +static unsigned char +em_file_open(const char *file, Evas_Object *obj __UNUSED__, void *data) +{ + Emotion_Generic_Video *ev = data; + INF("file set: %s", file); + if (!ev) return 0; + + eina_stringshare_replace(&ev->filename, file); + + ev->pos = 0; + ev->w = 0; + ev->h = 0; + ev->ratio = 1; + ev->len = 0; + + if (ev->ready && ev->opening) + { + INF("file changed while opening."); + ev->file_changed = EINA_TRUE; + return 1; + } + + ev->opening = EINA_TRUE; + + if (!ev->closing) + _file_open(ev); + + return 1; +} + +static void +em_file_close(void *data) +{ + Emotion_Generic_Video *ev = data; + + if (!ev || !ev->filename) return; + + INF("file close: %s", ev->filename); + + eina_stringshare_replace(&ev->filename, NULL); + + ev->file_ready = EINA_FALSE; + _audio_channels_free(ev); + _video_channels_free(ev); + _spu_channels_free(ev); + _player_meta_info_free(ev); + + if (ev->opening) + return; + + _player_send_cmd(ev, EM_CMD_FILE_CLOSE); + ev->closing = EINA_TRUE; +} + +static Emotion_Format +em_format_get(void *ef __UNUSED__) +{ + return EMOTION_FORMAT_BGRA; +} + +static void +em_video_data_size_get(void *data, int *w, int *h) +{ + Emotion_Generic_Video *ev = data; + + if (!ev) return; + if (w) *w = ev->w; + if (h) *h = ev->h; +} + +static void +em_play(void *data, double pos) +{ + Emotion_Generic_Video *ev = data; + + if (!ev) + return; + + ev->play = EINA_TRUE; + INF("play: %0.3f", pos); + + if (ev->initializing || ev->opening) + return; + + if (ev->ready) + { + _player_send_cmd(ev, EM_CMD_PLAY); + _player_send_float(ev, ev->pos); + return; + } + + if (!_player_exec(ev)) + ERR("could not start player."); +} + +static void +em_stop(void *data) +{ + Emotion_Generic_Video *ev = data; + + if (!ev) + return; + + ev->play = EINA_FALSE; + + if (!ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_STOP); + _emotion_decode_stop(ev->obj); +} + +static void +em_size_get(void *data, int *w, int *h) +{ + Emotion_Generic_Video *ev = data; + if (w) *w = ev->w; + if (h) *h = ev->h; +} + +static void +em_pos_set(void *data, double pos) +{ + Emotion_Generic_Video *ev = data; + float position = pos; + + if (!ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_POSITION_SET); + _player_send_float(ev, position); + _emotion_seek_done(ev->obj); +} + +static double +em_len_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->len; +} + +static double +em_buffer_size_get(void *data __UNUSED__) +{ + return 1.0; +} + +static int +em_fps_num_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return (int)(ev->fps * 1000.0); +} + +static int +em_fps_den_get(void *ef __UNUSED__) +{ + return 1000; +} + +static double +em_fps_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->fps; +} + +static double +em_pos_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->pos; +} + +static void +em_vis_set(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__) +{ +} + +static Emotion_Vis +em_vis_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->vis; +} + +static Eina_Bool +em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis __UNUSED__) +{ + return EINA_FALSE; +} + +static double +em_ratio_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->ratio; +} + +static int em_video_handled(void *ef __UNUSED__) +{ + fprintf(stderr, "video handled!\n"); + return 1; +} + +static int em_audio_handled(void *ef __UNUSED__) +{ + fprintf(stderr, "audio handled!\n"); + return 1; +} + +static int em_seekable(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->seekable; +} + +static void em_frame_done(void *ef __UNUSED__) +{ +} + +static int +em_yuv_rows_get(void *data __UNUSED__, int w __UNUSED__, int h __UNUSED__, unsigned char **yrows __UNUSED__, unsigned char **urows __UNUSED__, unsigned char **vrows __UNUSED__) +{ + return 0; +} + +static int +em_bgra_data_get(void *data, unsigned char **bgra_data) +{ + Emotion_Generic_Video *ev = data; + + if (!ev || !ev->file_ready) + return 0; + + // lock frame here + if (!eina_semaphore_lock(&ev->shared->lock)) + return 0; + + // send current frame to emotion + if (ev->shared->frame.emotion != ev->shared->frame.last) + { + ev->shared->frame.next = ev->shared->frame.emotion; + ev->shared->frame.emotion = ev->shared->frame.last; + } + *bgra_data = ev->frame.frames[ev->shared->frame.emotion]; + + if (ev->shared->frame_drop > 1) + WRN("dropped frames: %d", ev->shared->frame_drop - 1); + ev->shared->frame_drop = 0; + + // unlock frame here + eina_semaphore_release(&ev->shared->lock, 1); + ev->drop = 0; + + return 1; +} + +static void +em_event_feed(void *ef __UNUSED__, int event __UNUSED__) +{ +} + +static void +em_event_mouse_button_feed(void *ef __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__) +{ +} + +static void +em_event_mouse_move_feed(void *ef __UNUSED__, int x __UNUSED__, int y __UNUSED__) +{ +} + +static int +em_video_channel_count(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->video_channels_count; +} + +static void +em_video_channel_set(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->video_channels_count) + { + WRN("video channel out of range."); + return; + } + + _player_send_cmd(ev, EM_CMD_VIDEO_TRACK_SET); + _player_send_int(ev, ev->video_channels[channel].id); + ev->video_channel_current = channel; +} + +static int +em_video_channel_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->video_channel_current; +} + +static const char * +em_video_channel_name_get(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->video_channels_count) + { + WRN("video channel out of range."); + return NULL; + } + + return ev->video_channels[channel].name; +} + +static void +em_video_channel_mute_set(void *data, int mute) +{ + Emotion_Generic_Video *ev = data; + + ev->video_mute = !!mute; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_VIDEO_MUTE_SET); + _player_send_int(ev, mute); +} + +static int +em_video_channel_mute_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->video_mute; +} + +static int +em_audio_channel_count(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->audio_channels_count; +} + +static void +em_audio_channel_set(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->audio_channels_count) + { + WRN("audio channel out of range."); + return; + } + + _player_send_cmd(ev, EM_CMD_AUDIO_TRACK_SET); + _player_send_int(ev, ev->audio_channels[channel].id); + ev->audio_channel_current = channel; +} + +static int +em_audio_channel_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->audio_channel_current; +} + +static const char * +em_audio_channel_name_get(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->audio_channels_count) + { + WRN("audio channel out of range."); + return NULL; + } + + return ev->audio_channels[channel].name; +} + +static void +em_audio_channel_mute_set(void *data, int mute) +{ + Emotion_Generic_Video *ev = data; + + ev->audio_mute = !!mute; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_AUDIO_MUTE_SET); + _player_send_int(ev, mute); +} + +static int +em_audio_channel_mute_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->audio_mute; +} + +static void +em_audio_channel_volume_set(void *data, double vol) +{ + Emotion_Generic_Video *ev = data; + + if (vol > 1.0) vol = 1.0; + if (vol < 0.0) vol = 0.0; + + ev->volume = vol; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_VOLUME_SET); + _player_send_float(ev, ev->volume); +} + +static double +em_audio_channel_volume_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->volume; +} + +static int +em_spu_channel_count(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->spu_channels_count; +} + +static void +em_spu_channel_set(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->spu_channels_count) + { + WRN("spu channel out of range."); + return; + } + + _player_send_cmd(ev, EM_CMD_SPU_TRACK_SET); + _player_send_int(ev, ev->spu_channels[channel].id); + ev->spu_channel_current = channel; +} + +static int +em_spu_channel_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->spu_channel_current; +} + +static const char * +em_spu_channel_name_get(void *data, int channel) +{ + Emotion_Generic_Video *ev = data; + + if (channel < 0 || channel >= ev->spu_channels_count) + { + WRN("spu channel out of range."); + return NULL; + } + + return ev->spu_channels[channel].name; +} + +static void +em_spu_channel_mute_set(void *data, int mute) +{ + Emotion_Generic_Video *ev = data; + + ev->spu_mute = !!mute; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_SPU_MUTE_SET); + _player_send_int(ev, mute); +} + +static int +em_spu_channel_mute_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return ev->spu_mute; +} + +static int +em_chapter_count(void *ef __UNUSED__) +{ + int num = 0; + return num; +} + +static void +em_chapter_set(void *ef __UNUSED__, int chapter __UNUSED__) +{ +} + +static int +em_chapter_get(void *ef __UNUSED__) +{ + int num = 0; + return num; +} + +static const char * +em_chapter_name_get(void *ef __UNUSED__, int chapter __UNUSED__) +{ + return NULL; +} + +static void +em_speed_set(void *data, double speed) +{ + Emotion_Generic_Video *ev = data; + float rate = speed; + ev->speed = rate; + + if (!ev || !ev->file_ready) + return; + + _player_send_cmd(ev, EM_CMD_SPEED_SET); + _player_send_float(ev, rate); +} + +static double +em_speed_get(void *data) +{ + Emotion_Generic_Video *ev = data; + return (double)ev->speed; +} + +static int +em_eject(void *ef __UNUSED__) +{ + return 1; +} + +static const char * +em_meta_get(void *data, int meta) +{ + Emotion_Generic_Video *ev = data; + + switch (meta) { + case EMOTION_META_INFO_TRACK_TITLE: + return ev->meta.title; + case EMOTION_META_INFO_TRACK_ARTIST: + return ev->meta.artist; + case EMOTION_META_INFO_TRACK_ALBUM: + return ev->meta.album; + case EMOTION_META_INFO_TRACK_YEAR: + return ev->meta.year; + case EMOTION_META_INFO_TRACK_GENRE: + return ev->meta.genre; + case EMOTION_META_INFO_TRACK_COMMENT: + return ev->meta.comment; + case EMOTION_META_INFO_TRACK_DISC_ID: + return ev->meta.disc_id; + case EMOTION_META_INFO_TRACK_COUNT: + return ev->meta.count; + } + + return NULL; +} + +static Emotion_Video_Module em_module = +{ + em_init, /* init */ + em_shutdown, /* shutdown */ + em_file_open, /* file_open */ + em_file_close, /* file_close */ + em_play, /* play */ + em_stop, /* stop */ + em_size_get, /* size_get */ + em_pos_set, /* pos_set */ + em_len_get, /* len_get */ + em_buffer_size_get, /* buffer_size_get */ + em_fps_num_get, /* fps_num_get */ + em_fps_den_get, /* fps_den_get */ + em_fps_get, /* fps_get */ + em_pos_get, /* pos_get */ + em_vis_set, /* vis_set */ + em_vis_get, /* vis_get */ + em_vis_supported, /* vis_supported */ + em_ratio_get, /* ratio_get */ + em_video_handled, /* video_handled */ + em_audio_handled, /* audio_handled */ + em_seekable, /* seekable */ + em_frame_done, /* frame_done */ + em_format_get, /* format_get */ + em_video_data_size_get, /* video_data_size_get */ + em_yuv_rows_get, /* yuv_rows_get */ + em_bgra_data_get, /* bgra_data_get */ + em_event_feed, /* event_feed */ + em_event_mouse_button_feed, /* event_mouse_button_feed */ + em_event_mouse_move_feed, /* event_mouse_move_feed */ + em_video_channel_count, /* video_channel_count */ + em_video_channel_set, /* video_channel_set */ + em_video_channel_get, /* video_channel_get */ + em_video_channel_name_get, /* video_channel_name_get */ + em_video_channel_mute_set, /* video_channel_mute_set */ + em_video_channel_mute_get, /* video_channel_mute_get */ + em_audio_channel_count, /* audio_channel_count */ + em_audio_channel_set, /* audio_channel_set */ + em_audio_channel_get, /* audio_channel_get */ + em_audio_channel_name_get, /* audio_channel_name_get */ + em_audio_channel_mute_set, /* audio_channel_mute_set */ + em_audio_channel_mute_get, /* audio_channel_mute_get */ + em_audio_channel_volume_set, /* audio_channel_volume_set */ + em_audio_channel_volume_get, /* audio_channel_volume_get */ + em_spu_channel_count, /* spu_channel_count */ + em_spu_channel_set, /* spu_channel_set */ + em_spu_channel_get, /* spu_channel_get */ + em_spu_channel_name_get, /* spu_channel_name_get */ + em_spu_channel_mute_set, /* spu_channel_mute_set */ + em_spu_channel_mute_get, /* spu_channel_mute_get */ + em_chapter_count, /* chapter_count */ + em_chapter_set, /* chapter_set */ + em_chapter_get, /* chapter_get */ + em_chapter_name_get, /* chapter_name_get */ + em_speed_set, /* speed_set */ + em_speed_get, /* speed_get */ + em_eject, /* eject */ + em_meta_get, /* meta_get */ + NULL, /* priority_set */ + NULL, /* priority_get */ + NULL /* handle */ +}; + +static Eina_Bool +module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt) +{ + if (!module) { + return EINA_FALSE; + } + + if (_emotion_generic_log_domain < 0) + { + eina_threads_init(); + eina_log_threads_enable(); + _emotion_generic_log_domain = eina_log_domain_register + ("emotion-generic", EINA_COLOR_LIGHTCYAN); + if (_emotion_generic_log_domain < 0) + { + EINA_LOG_CRIT("Could not register log domain 'emotion-generic'"); + return EINA_FALSE; + } + } + + + if (!em_module.init(obj, video, opt)) { + return EINA_FALSE; + } + + *module = &em_module; + + return EINA_TRUE; +} + +static void module_close(Emotion_Video_Module *module __UNUSED__, void *video) +{ + em_module.shutdown(video); +} + + +Eina_Bool +generic_module_init(void) +{ + if (!pfx) + { + pfx = eina_prefix_new(NULL, emotion_object_add, + "EMOTION", "emotion", NULL, + PACKAGE_BIN_DIR, + PACKAGE_LIB_DIR, + PACKAGE_DATA_DIR, + ""); + if (!pfx) return EINA_FALSE; + } + return _emotion_module_register("generic", module_open, module_close); +} + +static void +generic_module_shutdown(void) +{ + if (pfx) + { + eina_prefix_free(pfx); + pfx = NULL; + } + _emotion_module_unregister("generic"); +} + +#ifndef EMOTION_STATIC_BUILD_GENERIC + +EINA_MODULE_INIT(generic_module_init); +EINA_MODULE_SHUTDOWN(generic_module_shutdown); + +#endif + diff --git a/src/modules/generic/emotion_generic.h b/src/modules/generic/emotion_generic.h new file mode 100644 index 0000000..ed3bdb0 --- /dev/null +++ b/src/modules/generic/emotion_generic.h @@ -0,0 +1,112 @@ +#ifndef EMOTION_GENERIC_H +#define EMOTION_GENERIC_H + +#include "Emotion_Generic_Plugin.h" + +/* default values */ + +typedef struct _Emotion_Generic_Video Emotion_Generic_Video; +typedef struct _Emotion_Generic_Player Emotion_Generic_Player; +typedef struct _Emotion_Generic_Cmd_Buffer Emotion_Generic_Cmd_Buffer; +typedef struct _Emotion_Generic_Channel Emotion_Generic_Channel; +typedef struct _Emotion_Generic_Meta Emotion_Generic_Meta; + +struct _Emotion_Generic_Player +{ + Ecore_Exe *exe; +}; + +struct _Emotion_Generic_Channel +{ + int id; + const char *name; +}; + +struct _Emotion_Generic_Meta +{ + const char *title; + const char *artist; + const char *album; + const char *year; + const char *genre; + const char *comment; + const char *disc_id; + const char *count; +}; + +struct _Emotion_Generic_Cmd_Buffer +{ + char *tmp; + int type; + ssize_t i, total; + int s_len; + int num_params, cur_param; + int padding; + union { + struct { + int width; + int height; + } size; + int i_num; + float f_num; + struct { + int total; + int current; + Emotion_Generic_Channel *channels; + } track; + Emotion_Generic_Meta meta; + } param; +}; + +/* emotion/generic main structure */ +struct _Emotion_Generic_Video +{ + const char *cmdline; + const char *shmname; + + Emotion_Generic_Player player; + Emotion_Generic_Cmd_Buffer cmd; + Ecore_Event_Handler *player_add, *player_del, *player_data; + Ecore_Idler *player_restart; + int drop; + int fd_read, fd_write; + Ecore_Fd_Handler *fd_handler; + + const char *filename; + volatile double len; + volatile double pos; + double fps; + double ratio; + int w, h; + Evas_Object *obj; + Emotion_Generic_Video_Shared *shared; + Emotion_Generic_Video_Frame frame; + volatile int fq; + float volume; + float speed; + Emotion_Vis vis; + Eina_Bool initializing : 1; + Eina_Bool ready : 1; + Eina_Bool play : 1; + Eina_Bool video_mute : 1; + Eina_Bool audio_mute : 1; + Eina_Bool spu_mute : 1; + Eina_Bool seekable : 1; + volatile Eina_Bool opening : 1; + volatile Eina_Bool closing : 1; + Eina_Bool file_changed : 1; + Eina_Bool file_ready : 1; + int audio_channels_count; + int audio_channel_current; + Emotion_Generic_Channel *audio_channels; + int video_channels_count; + int video_channel_current; + Emotion_Generic_Channel *video_channels; + int spu_channels_count; + int spu_channel_current; + Emotion_Generic_Channel *spu_channels; + Emotion_Generic_Meta meta; +}; + +#endif + diff --git a/src/modules/gstreamer/Makefile.am b/src/modules/gstreamer/Makefile.am index f3519af..3672510 100644 --- a/src/modules/gstreamer/Makefile.am +++ b/src/modules/gstreamer/Makefile.am @@ -1,4 +1,3 @@ - MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = \ @@ -7,27 +6,32 @@ 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 diff --git a/src/modules/gstreamer/emotion_alloc.c b/src/modules/gstreamer/emotion_alloc.c new file mode 100644 index 0000000..05062bd --- /dev/null +++ b/src/modules/gstreamer/emotion_alloc.c @@ -0,0 +1,91 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + +#include "Emotion.h" +#include "emotion_gstreamer.h" + +Emotion_Gstreamer_Buffer * +emotion_gstreamer_buffer_alloc(EvasVideoSinkPrivate *sink, + GstBuffer *buffer, + Eina_Bool preroll) +{ + Emotion_Gstreamer_Buffer *send; + + if (!sink->ev) return NULL; + + send = malloc(sizeof (Emotion_Gstreamer_Buffer)); + if (!send) return NULL; + + send->sink = sink; + send->frame = gst_buffer_ref(buffer); + send->preroll = preroll; + send->force = EINA_FALSE; + sink->ev->out++; + send->ev = sink->ev; + + return send; +} + +void +emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send) +{ + send->ev->in++; + + if (send->ev->in == send->ev->out + && send->ev->threads == NULL + && send->ev->delete_me) + em_shutdown(send->ev); + + gst_buffer_unref(send->frame); + free(send); +} + +Emotion_Gstreamer_Message * +emotion_gstreamer_message_alloc(Emotion_Gstreamer_Video *ev, + GstMessage *msg) +{ + Emotion_Gstreamer_Message *send; + + if (!ev) return NULL; + + send = malloc(sizeof (Emotion_Gstreamer_Message)); + if (!send) return NULL; + + ev->out++; + send->ev = ev; + send->msg = gst_message_ref(msg); + + return send; +} + +void +emotion_gstreamer_message_free(Emotion_Gstreamer_Message *send) +{ + send->ev->in++; + + if (send->ev->in == send->ev->out + && send->ev->threads == NULL + && send->ev->delete_me) + em_shutdown(send->ev); + + gst_message_unref(send->msg); + free(send); +} diff --git a/src/modules/gstreamer/emotion_convert.c b/src/modules/gstreamer/emotion_convert.c new file mode 100644 index 0000000..3d3b46e --- /dev/null +++ b/src/modules/gstreamer/emotion_convert.c @@ -0,0 +1,252 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + +#include "Emotion.h" +#include "emotion_gstreamer.h" + +static inline void +_evas_video_bgrx_step(unsigned char *evas_data, const unsigned char *gst_data, + unsigned int w, unsigned int h __UNUSED__, unsigned int output_height, unsigned int step) +{ + unsigned int x; + unsigned int y; + + for (y = 0; y < output_height; ++y) + { + for (x = 0; x < w; x++) + { + evas_data[0] = gst_data[0]; + evas_data[1] = gst_data[1]; + evas_data[2] = gst_data[2]; + evas_data[3] = 255; + gst_data += step; + evas_data += 4; + } + } +} + +static void +_evas_video_bgr(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +{ + _evas_video_bgrx_step(evas_data, gst_data, w, h, output_height, 3); +} + +static void +_evas_video_bgrx(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +{ + _evas_video_bgrx_step(evas_data, gst_data, w, h, output_height, 4); +} + +static void +_evas_video_bgra(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h __UNUSED__, unsigned int output_height) +{ + unsigned int x; + unsigned int y; + + for (y = 0; y < output_height; ++y) + { + unsigned char alpha; + + for (x = 0; x < w; ++x) + { + alpha = gst_data[3]; + evas_data[0] = (gst_data[0] * alpha) / 255; + evas_data[1] = (gst_data[1] * alpha) / 255; + evas_data[2] = (gst_data[2] * alpha) / 255; + evas_data[3] = alpha; + gst_data += 4; + evas_data += 4; + } + } +} + +static void +_evas_video_i420(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +{ + const unsigned char **rows; + unsigned int i, j; + unsigned int rh; + unsigned int stride_y, stride_uv; + + rh = output_height; + + rows = (const unsigned char **)evas_data; + + stride_y = GST_ROUND_UP_4(w); + stride_uv = GST_ROUND_UP_8(w) / 2; + + for (i = 0; i < rh; i++) + rows[i] = &gst_data[i * stride_y]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[h * stride_y + j * stride_uv]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[h * stride_y + + (rh / 2) * stride_uv + + j * stride_uv]; +} + +static void +_evas_video_yv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +{ + const unsigned char **rows; + unsigned int i, j; + unsigned int rh; + unsigned int stride_y, stride_uv; + + rh = output_height; + + rows = (const unsigned char **)evas_data; + + stride_y = GST_ROUND_UP_4(w); + stride_uv = GST_ROUND_UP_8(w) / 2; + + for (i = 0; i < rh; i++) + rows[i] = &gst_data[i * stride_y]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[h * stride_y + + (rh / 2) * stride_uv + + j * stride_uv]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[h * stride_y + j * stride_uv]; +} + +static void +_evas_video_yuy2(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h __UNUSED__, unsigned int output_height) +{ + const unsigned char **rows; + unsigned int i; + unsigned int stride; + + rows = (const unsigned char **)evas_data; + + stride = GST_ROUND_UP_4(w * 2); + + for (i = 0; i < output_height; i++) + rows[i] = &gst_data[i * stride]; +} + +static void +_evas_video_nv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h __UNUSED__, unsigned int output_height) +{ + const unsigned char **rows; + unsigned int i, j; + unsigned int rh; + + rh = output_height; + + rows = (const unsigned char **)evas_data; + + for (i = 0; i < rh; i++) + rows[i] = &gst_data[i * w]; + + for (j = 0; j < (rh / 2); j++, i++) + rows[i] = &gst_data[rh * w + j * w]; +} + +static void +_evas_video_mt12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height __UNUSED__) +{ + const unsigned char **rows; + unsigned int i; + unsigned int j; + + rows = (const unsigned char **)evas_data; + + for (i = 0; i < (h / 32) / 2; i++) + rows[i] = &gst_data[i * w * 2 * 32]; + + if ((h / 32) % 2) + { + rows[i] = &gst_data[i * w * 2 * 32]; + i++; + } + + for (j = 0; j < ((h / 2) / 32) / 2; ++j, ++i) + rows[i] = &gst_data[h * w + j * (w / 2) * 2 * 16]; +} + +void +_evas_video_st12_multiplane(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height __UNUSED__) +{ + const GstMultiPlaneImageBuffer *mp_buf = (const GstMultiPlaneImageBuffer *) gst_data; + const unsigned char **rows; + unsigned int i; + unsigned int j; + + rows = (const unsigned char **)evas_data; + + for (i = 0; i < (h / 32) / 2; i++) + rows[i] = mp_buf->uaddr[0] + i * w * 2 * 32; + if ((h / 32) % 2) + { + rows[i] = mp_buf->uaddr[0] + i * w * 2 * 32; + i++; + } + + for (j = 0; j < ((h / 2) / 16) / 2; j++, i++) + { + rows[i] = mp_buf->uaddr[1] + j * w * 2 * 16 * 2; + } + if (((h / 2) / 16) % 2) + rows[i] = mp_buf->uaddr[1] + j * w * 2 * 16 * 2; +} + +void +_evas_video_st12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w __UNUSED__, unsigned int h, unsigned int output_height __UNUSED__) +{ + const SCMN_IMGB *imgb = (const SCMN_IMGB *) gst_data; + const unsigned char **rows; + unsigned int i, j; + + rows = (const unsigned char **)evas_data; + + for (i = 0; i < (h / 32) / 2; i++) + rows[i] = imgb->uaddr[0] + i * imgb->stride[0] * 2 * 32; + if ((h / 32) % 2) + { + rows[i] = imgb->uaddr[0] + i * imgb->stride[0] * 2 * 32; + i++; + } + + for (j = 0; j < (unsigned int) imgb->elevation[1] / 32 / 2; j++, i++) + rows[i] = imgb->uaddr[1] + j * imgb->stride[1] * 32 * 2; + if ((imgb->elevation[1] / 32) % 2) + rows[i++] = imgb->uaddr[1] + j * imgb->stride[1] * 32 * 2; +} + +const ColorSpace_FourCC_Convertion colorspace_fourcc_convertion[] = { + { "I420", GST_MAKE_FOURCC('I', '4', '2', '0'), EVAS_COLORSPACE_YCBCR422P601_PL, _evas_video_i420, EINA_TRUE }, + { "YV12", GST_MAKE_FOURCC('Y', 'V', '1', '2'), EVAS_COLORSPACE_YCBCR422P601_PL, _evas_video_yv12, EINA_TRUE }, + { "YUY2", GST_MAKE_FOURCC('Y', 'U', 'Y', '2'), EVAS_COLORSPACE_YCBCR422601_PL, _evas_video_yuy2, EINA_FALSE }, + { "NV12", GST_MAKE_FOURCC('N', 'V', '1', '2'), EVAS_COLORSPACE_YCBCR420NV12601_PL, _evas_video_nv12, EINA_TRUE }, + { "TM12", GST_MAKE_FOURCC('T', 'M', '1', '2'), EVAS_COLORSPACE_YCBCR420TM12601_PL, _evas_video_mt12, EINA_TRUE }, + { NULL, 0, 0, NULL, 0 } +}; + +const ColorSpace_Format_Convertion colorspace_format_convertion[] = { + { "BGR", GST_VIDEO_FORMAT_BGR, EVAS_COLORSPACE_ARGB8888, _evas_video_bgr }, + { "BGRx", GST_VIDEO_FORMAT_BGRx, EVAS_COLORSPACE_ARGB8888, _evas_video_bgrx }, + { "BGRA", GST_VIDEO_FORMAT_BGRA, EVAS_COLORSPACE_ARGB8888, _evas_video_bgra }, + { NULL, 0, 0, NULL } +}; diff --git a/src/modules/gstreamer/emotion_fakeeos.c b/src/modules/gstreamer/emotion_fakeeos.c new file mode 100644 index 0000000..a9e1bbe --- /dev/null +++ b/src/modules/gstreamer/emotion_fakeeos.c @@ -0,0 +1,71 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + +#include "Emotion.h" +#include "emotion_gstreamer.h" + +typedef struct _FakeEOSBin +{ + GstBin parent; +} FakeEOSBin; + +typedef struct _FakeEOSBinClass +{ + GstBinClass parent; +} FakeEOSBinClass; + +GST_BOILERPLATE(FakeEOSBin, fakeeos_bin, GstBin, + GST_TYPE_BIN); + +static void +fakeeos_bin_handle_message(GstBin * bin, GstMessage * message) +{ + /* FakeEOSBin *fakeeos = (FakeEOSBin *)(bin); */ + + switch (GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_EOS: + /* what to do here ? just returning at the moment */ + return ; + default: + break; + } + + GST_BIN_CLASS(parent_class)->handle_message(bin, message); +} + +static void +fakeeos_bin_base_init(gpointer g_class __UNUSED__) +{ +} + +static void +fakeeos_bin_class_init(FakeEOSBinClass * klass) +{ + GstBinClass *gstbin_class = GST_BIN_CLASS(klass); + + gstbin_class->handle_message = + GST_DEBUG_FUNCPTR (fakeeos_bin_handle_message); +} + +static void +fakeeos_bin_init(FakeEOSBin *src __UNUSED__, + FakeEOSBinClass *klass __UNUSED__) +{ +} diff --git a/src/modules/gstreamer/emotion_gstreamer.c b/src/modules/gstreamer/emotion_gstreamer.c index 4bb6348..8ec71fb 100644 --- a/src/modules/gstreamer/emotion_gstreamer.c +++ b/src/modules/gstreamer/emotion_gstreamer.c @@ -1,18 +1,44 @@ -/* - * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 - */ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif #include +#include +#include +#include + +#define HTTP_STREAM 0 +#define RTSP_STREAM 1 +#include +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + #include "Emotion.h" #include "emotion_private.h" #include "emotion_gstreamer.h" -#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); @@ -20,9 +46,7 @@ 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, @@ -42,11 +66,11 @@ static void em_size_get (void *video, 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); @@ -55,8 +79,14 @@ static double em_fps_get (void *video); static double em_pos_get (void *video); +static void em_vis_set (void *video, + Emotion_Vis vis); + static Emotion_Vis em_vis_get (void *video); +static Eina_Bool em_vis_supported (void *video, + Emotion_Vis vis); + static double em_ratio_get (void *video); static int em_video_handled (void *video); @@ -165,6 +195,16 @@ static int em_eject (void *video); static const char *em_meta_get (void *video, int meta); +static void em_priority_set (void *video, + Eina_Bool pri); +static Eina_Bool em_priority_get (void *video); + +static GstBusSyncReply _eos_sync_fct(GstBus *bus, + GstMessage *message, + gpointer data); + +static Eina_Bool _em_restart_stream(void *data); + /* Module interface */ static Emotion_Video_Module em_module = @@ -177,13 +217,15 @@ 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 */ @@ -224,17 +266,87 @@ static Emotion_Video_Module em_module = 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; @@ -243,59 +355,107 @@ em_init(Evas_Object *obj, 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; @@ -304,16 +464,24 @@ em_shutdown(void *video) 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); @@ -323,133 +491,64 @@ em_shutdown(void *video) 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; } @@ -462,49 +561,33 @@ em_file_close(void *video) 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 @@ -514,114 +597,148 @@ em_stop(void *video) 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; } @@ -630,13 +747,16 @@ static int 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; } @@ -645,13 +765,16 @@ static double 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; } @@ -660,12 +783,41 @@ static double 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) { @@ -676,6 +828,27 @@ 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) { @@ -693,7 +866,9 @@ em_video_handled(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; @@ -706,54 +881,52 @@ em_audio_handled(void *video) 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; } @@ -762,106 +935,58 @@ static void 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 */ @@ -872,18 +997,22 @@ em_video_channel_count(void *video) 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... */ } @@ -894,23 +1023,21 @@ em_video_channel_get(void *video) 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; @@ -938,18 +1065,22 @@ em_audio_channel_count(void *video) 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... */ } @@ -960,42 +1091,38 @@ em_audio_channel_get(void *video) 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 @@ -1010,23 +1137,20 @@ em_audio_channel_mute_get(void *video) 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 @@ -1042,122 +1166,76 @@ em_audio_channel_volume_get(void *video) /* 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; } @@ -1165,7 +1243,7 @@ static const char * em_meta_get(void *video, int meta) { Emotion_Gstreamer_Video *ev; - const char *str; + const char *str = NULL; ev = (Emotion_Gstreamer_Video *)video; @@ -1173,63 +1251,237 @@ em_meta_get(void *video, int meta) 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; @@ -1239,102 +1491,101 @@ _for_each_tag(GstTagList const* list, 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 } @@ -1345,96 +1596,541 @@ _free_metadata(Emotion_Gstreamer_Metadata *m) { 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; } diff --git a/src/modules/gstreamer/emotion_gstreamer.h b/src/modules/gstreamer/emotion_gstreamer.h index b335604..9c7455d 100644 --- a/src/modules/gstreamer/emotion_gstreamer.h +++ b/src/modules/gstreamer/emotion_gstreamer.h @@ -1,46 +1,40 @@ -/* - * 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 -#include -#include - -#define HTTP_STREAM 0 -#define RTSP_STREAM 1 -#include - -#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; @@ -53,28 +47,36 @@ struct _Emotion_Gstreamer_Metadata 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; @@ -83,27 +85,246 @@ struct _Emotion_Gstreamer_Video 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__ */ diff --git a/src/modules/gstreamer/emotion_sink.c b/src/modules/gstreamer/emotion_sink.c new file mode 100644 index 0000000..17a1bc5 --- /dev/null +++ b/src/modules/gstreamer/emotion_sink.c @@ -0,0 +1,1391 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#define HTTP_STREAM 0 +#define RTSP_STREAM 1 +#include +#include +#include +#include +#include + +#ifdef HAVE_ECORE_X +# include +# include +# ifdef HAVE_XOVERLAY_H +# include +# endif +#endif + +#include "Emotion.h" +#include "emotion_private.h" +#include "emotion_gstreamer.h" + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE("sink", + GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS(GST_VIDEO_CAPS_YUV("{ I420, YV12, YUY2, NV12, ST12, TM12 }") ";" + GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_BGR ";" GST_VIDEO_CAPS_BGRA)); + +GST_DEBUG_CATEGORY_STATIC(evas_video_sink_debug); +#define GST_CAT_DEFAULT evas_video_sink_debug + +enum { + REPAINT_REQUESTED, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_EVAS_OBJECT, + PROP_WIDTH, + PROP_HEIGHT, + PROP_EV, + PROP_LAST +}; + +static guint evas_video_sink_signals[LAST_SIGNAL] = { 0, }; + +#define _do_init(bla) \ + GST_DEBUG_CATEGORY_INIT(evas_video_sink_debug, \ + "emotion-sink", \ + 0, \ + "emotion video sink") + +GST_BOILERPLATE_FULL(EvasVideoSink, + evas_video_sink, + GstVideoSink, + GST_TYPE_VIDEO_SINK, + _do_init); + + +static void unlock_buffer_mutex(EvasVideoSinkPrivate* priv); +static void evas_video_sink_main_render(void *data); +static void evas_video_sink_samsung_main_render(void *data); + +static void +evas_video_sink_base_init(gpointer g_class) +{ + GstElementClass* element_class; + + element_class = GST_ELEMENT_CLASS(g_class); + gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sinktemplate)); + gst_element_class_set_details_simple(element_class, "Evas video sink", + "Sink/Video", "Sends video data from a GStreamer pipeline to an Evas object", + "Vincent Torri "); +} + +static void +evas_video_sink_init(EvasVideoSink* sink, EvasVideoSinkClass* klass __UNUSED__) +{ + EvasVideoSinkPrivate* priv; + + INF("sink init"); + sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, EVAS_TYPE_VIDEO_SINK, EvasVideoSinkPrivate); + priv->o = NULL; + priv->width = 0; + priv->height = 0; + priv->func = NULL; + priv->eformat = EVAS_COLORSPACE_ARGB8888; + priv->samsung = EINA_FALSE; + eina_lock_new(&priv->m); + eina_condition_new(&priv->c, &priv->m); + priv->unlocked = EINA_FALSE; +} + +/**** Object methods ****/ +static void +_cleanup_priv(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + EvasVideoSinkPrivate* priv; + + priv = data; + + eina_lock_take(&priv->m); + if (priv->o == obj) + priv->o = NULL; + eina_lock_release(&priv->m); +} + +static void +evas_video_sink_set_property(GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + + sink = EVAS_VIDEO_SINK (object); + priv = sink->priv; + + switch (prop_id) { + case PROP_EVAS_OBJECT: + eina_lock_take(&priv->m); + evas_object_event_callback_del(priv->o, EVAS_CALLBACK_FREE, _cleanup_priv); + priv->o = g_value_get_pointer (value); + INF("sink set Evas_Object %p.", priv->o); + evas_object_event_callback_add(priv->o, EVAS_CALLBACK_FREE, _cleanup_priv, priv); + eina_lock_release(&priv->m); + break; + case PROP_EV: + INF("sink set ev."); + eina_lock_take(&priv->m); + priv->ev = g_value_get_pointer (value); + if (priv->ev) + priv->ev->samsung = EINA_TRUE; + eina_lock_release(&priv->m); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + ERR("invalid property"); + break; + } +} + +static void +evas_video_sink_get_property(GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + + sink = EVAS_VIDEO_SINK (object); + priv = sink->priv; + + switch (prop_id) { + case PROP_EVAS_OBJECT: + INF("sink get property."); + eina_lock_take(&priv->m); + g_value_set_pointer(value, priv->o); + eina_lock_release(&priv->m); + break; + case PROP_WIDTH: + INF("sink get width."); + eina_lock_take(&priv->m); + g_value_set_int(value, priv->width); + eina_lock_release(&priv->m); + break; + case PROP_HEIGHT: + INF("sink get height."); + eina_lock_take(&priv->m); + g_value_set_int (value, priv->height); + eina_lock_release(&priv->m); + break; + case PROP_EV: + INF("sink get ev."); + eina_lock_take(&priv->m); + g_value_set_pointer (value, priv->ev); + eina_lock_release(&priv->m); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + ERR("invalide property"); + break; + } +} + +static void +evas_video_sink_dispose(GObject* object) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + + INF("dispose."); + + sink = EVAS_VIDEO_SINK(object); + priv = sink->priv; + + eina_lock_free(&priv->m); + eina_condition_free(&priv->c); + + G_OBJECT_CLASS(parent_class)->dispose(object); +} + + +/**** BaseSink methods ****/ + +gboolean evas_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + GstStructure *structure; + GstVideoFormat format; + guint32 fourcc; + unsigned int i; + + sink = EVAS_VIDEO_SINK(bsink); + priv = sink->priv; + + structure = gst_caps_get_structure(caps, 0); + + if (gst_structure_get_int(structure, "width", (int*) &priv->width) + && gst_structure_get_int(structure, "height", (int*) &priv->height) + && gst_structure_get_fourcc(structure, "format", &fourcc)) + { + priv->source_height = priv->height; + + for (i = 0; colorspace_fourcc_convertion[i].name != NULL; ++i) + if (fourcc == colorspace_fourcc_convertion[i].fourcc) + { + fprintf(stderr, "Found '%s'\n", colorspace_fourcc_convertion[i].name); + priv->eformat = colorspace_fourcc_convertion[i].eformat; + priv->func = colorspace_fourcc_convertion[i].func; + if (colorspace_fourcc_convertion[i].force_height) + { + priv->height = (priv->height >> 1) << 1; + } + if (priv->ev) + priv->ev->kill_buffer = EINA_TRUE; + return TRUE; + } + + if (fourcc == GST_MAKE_FOURCC('S', 'T', '1', '2')) + { + fprintf(stderr, "Found '%s'\n", "ST12"); + priv->eformat = EVAS_COLORSPACE_YCBCR420TM12601_PL; + priv->samsung = EINA_TRUE; + priv->func = NULL; + if (priv->ev) + { + priv->ev->samsung = EINA_TRUE; + priv->ev->kill_buffer = EINA_TRUE; + } + return TRUE; + } + } + + INF("fallback code !"); + if (!gst_video_format_parse_caps(caps, &format, (int*) &priv->width, (int*) &priv->height)) + { + ERR("Unable to parse caps."); + return FALSE; + } + + priv->source_height = priv->height; + + for (i = 0; colorspace_format_convertion[i].name != NULL; ++i) + if (format == colorspace_format_convertion[i].format) + { + fprintf(stderr, "Found '%s'\n", colorspace_format_convertion[i].name); + priv->eformat = colorspace_format_convertion[i].eformat; + priv->func = colorspace_format_convertion[i].func; + if (priv->ev) + priv->ev->kill_buffer = EINA_FALSE; + return TRUE; + } + + ERR("unsupported : %d\n", format); + return FALSE; +} + +static gboolean +evas_video_sink_start(GstBaseSink* base_sink) +{ + EvasVideoSinkPrivate* priv; + gboolean res = TRUE; + + INF("sink start"); + + priv = EVAS_VIDEO_SINK(base_sink)->priv; + eina_lock_take(&priv->m); + if (!priv->o) + res = FALSE; + else + priv->unlocked = EINA_FALSE; + eina_lock_release(&priv->m); + return res; +} + +static gboolean +evas_video_sink_stop(GstBaseSink* base_sink) +{ + EvasVideoSinkPrivate* priv = EVAS_VIDEO_SINK(base_sink)->priv; + + INF("sink stop"); + + unlock_buffer_mutex(priv); + return TRUE; +} + +static gboolean +evas_video_sink_unlock(GstBaseSink* object) +{ + EvasVideoSink* sink; + + INF("sink unlock"); + + sink = EVAS_VIDEO_SINK(object); + + unlock_buffer_mutex(sink->priv); + + return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock, + (object), TRUE); +} + +static gboolean +evas_video_sink_unlock_stop(GstBaseSink* object) +{ + EvasVideoSink* sink; + EvasVideoSinkPrivate* priv; + + sink = EVAS_VIDEO_SINK(object); + priv = sink->priv; + + INF("sink unlock stop"); + + eina_lock_take(&priv->m); + priv->unlocked = FALSE; + eina_lock_release(&priv->m); + + return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock_stop, + (object), TRUE); +} + +static GstFlowReturn +evas_video_sink_preroll(GstBaseSink* bsink, GstBuffer* buffer) +{ + Emotion_Gstreamer_Buffer *send; + EvasVideoSinkPrivate *priv; + EvasVideoSink *sink; + + INF("sink preroll %p [%i]", GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); + + sink = EVAS_VIDEO_SINK(bsink); + priv = sink->priv; + + if (GST_BUFFER_SIZE(buffer) <= 0 && !priv->samsung) + { + WRN("empty buffer"); + return GST_FLOW_OK; + } + + send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_TRUE); + + if (send) + { + if (priv->samsung) + { + if (!priv->func) + { + GstStructure *structure; + GstCaps *caps; + gboolean is_multiplane = FALSE; + + caps = GST_BUFFER_CAPS(buffer); + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_boolean(structure, "multiplane", &is_multiplane); + gst_caps_unref(caps); + + if (is_multiplane) + priv->func = _evas_video_st12_multiplane; + else + priv->func = _evas_video_st12; + } + + ecore_main_loop_thread_safe_call_async(evas_video_sink_samsung_main_render, send); + } + else + ecore_main_loop_thread_safe_call_async(evas_video_sink_main_render, send); + } + + return GST_FLOW_OK; +} + +static GstFlowReturn +evas_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer) +{ + Emotion_Gstreamer_Buffer *send; + EvasVideoSinkPrivate *priv; + EvasVideoSink *sink; + + INF("sink render %p", buffer); + + sink = EVAS_VIDEO_SINK(bsink); + priv = sink->priv; + + eina_lock_take(&priv->m); + + if (priv->unlocked) { + ERR("LOCKED"); + eina_lock_release(&priv->m); + return GST_FLOW_OK; + } + + send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_FALSE); + if (!send) { + eina_lock_release(&priv->m); + return GST_FLOW_ERROR; + } + + if (priv->samsung) + { + if (!priv->func) + { + GstStructure *structure; + GstCaps *caps; + gboolean is_multiplane = FALSE; + + caps = GST_BUFFER_CAPS(buffer); + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_boolean(structure, "multiplane", &is_multiplane); + gst_caps_unref(caps); + + if (is_multiplane) + priv->func = _evas_video_st12_multiplane; + else + priv->func = _evas_video_st12; + } + + ecore_main_loop_thread_safe_call_async(evas_video_sink_samsung_main_render, send); + } + else + ecore_main_loop_thread_safe_call_async(evas_video_sink_main_render, send); + + eina_condition_wait(&priv->c); + eina_lock_release(&priv->m); + + return GST_FLOW_OK; +} + +static void +_update_emotion_fps(Emotion_Gstreamer_Video *ev) +{ + double tim; + + if (!debug_fps) return ; + + tim = ecore_time_get(); + ev->frames++; + + if (ev->rlapse == 0.0) + { + ev->rlapse = tim; + ev->flapse = ev->frames; + } + else if ((tim - ev->rlapse) >= 0.5) + { + printf("FRAME: %i, FPS: %3.1f\n", + ev->frames, + (ev->frames - ev->flapse) / (tim - ev->rlapse)); + ev->rlapse = tim; + ev->flapse = ev->frames; + } +} + +static void +evas_video_sink_samsung_main_render(void *data) +{ + Emotion_Gstreamer_Buffer *send; + Emotion_Video_Stream *vstream; + EvasVideoSinkPrivate *priv = NULL; + GstBuffer* buffer; + unsigned char *evas_data; + const guint8 *gst_data; + GstFormat fmt = GST_FORMAT_TIME; + gint64 pos; + Eina_Bool preroll = EINA_FALSE; + int stride, elevation; + Evas_Coord w, h; + + send = data; + + if (!send) goto exit_point; + + priv = send->sink; + buffer = send->frame; + preroll = send->preroll; + + /* frame after cleanup */ + if (!preroll && !send->ev->last_buffer) + { + priv = NULL; + goto exit_point; + } + + if (!priv || !priv->o || priv->unlocked) + goto exit_point; + + if (send->ev->send) + { + emotion_gstreamer_buffer_free(send->ev->send); + send->ev->send = NULL; + } + + if (!send->ev->stream && !send->force) + { + send->ev->send = send; + _emotion_frame_new(send->ev->obj); + goto exit_stream; + } + + _emotion_gstreamer_video_pipeline_parse(send->ev, EINA_TRUE); + + /* Getting stride to compute the right size and then fill the object properly */ + /* Y => [0] and UV in [1] */ + if (priv->func == _evas_video_st12_multiplane) + { + const GstMultiPlaneImageBuffer *mp_buf = (const GstMultiPlaneImageBuffer *) buffer; + + stride = mp_buf->stride[0]; + elevation = mp_buf->elevation[0]; + priv->width = mp_buf->width[0]; + priv->height = mp_buf->height[0]; + + gst_data = (const guint8 *) mp_buf; + } + else + { + const SCMN_IMGB *imgb = (const SCMN_IMGB *) GST_BUFFER_MALLOCDATA(buffer); + + stride = imgb->stride[0]; + elevation = imgb->elevation[0]; + priv->width = imgb->width[0]; + priv->height = imgb->height[0]; + + gst_data = (const guint8 *) imgb; + } + + evas_object_geometry_get(priv->o, NULL, NULL, &w, &h); + + send->ev->fill.width = (double) stride / priv->width; + send->ev->fill.height = (double) elevation / priv->height; + + evas_object_image_alpha_set(priv->o, 0); + evas_object_image_colorspace_set(priv->o, priv->eformat); + evas_object_image_size_set(priv->o, stride, elevation); + + _update_emotion_fps(send->ev); + + evas_data = evas_object_image_data_get(priv->o, 1); + + if (priv->func) + priv->func(evas_data, gst_data, stride, elevation, elevation); + else + WRN("No way to decode %x colorspace !", priv->eformat); + + evas_object_image_data_set(priv->o, evas_data); + evas_object_image_data_update_add(priv->o, 0, 0, priv->width, priv->height); + evas_object_image_pixels_dirty_set(priv->o, 0); + + if (!preroll && send->ev->play_started) + { + _emotion_playback_started(send->ev->obj); + send->ev->play_started = 0; + } + + if (!send->force) + { + _emotion_frame_new(send->ev->obj); + } + + vstream = eina_list_nth(send->ev->video_streams, send->ev->video_stream_nbr - 1); + + gst_element_query_position(send->ev->pipeline, &fmt, &pos); + send->ev->position = (double)pos / (double)GST_SECOND; + + if (vstream) + { + vstream->width = priv->width; + vstream->height = priv->height; + + _emotion_video_pos_update(send->ev->obj, send->ev->position, vstream->length_time); + } + + send->ev->ratio = (double) priv->width / (double) priv->height; + _emotion_frame_refill(send->ev->obj, send->ev->fill.width, send->ev->fill.height); + _emotion_frame_resize(send->ev->obj, priv->width, priv->height, send->ev->ratio); + + buffer = gst_buffer_ref(buffer); + if (send->ev->last_buffer) gst_buffer_unref(send->ev->last_buffer); + send->ev->last_buffer = buffer; + + exit_point: + emotion_gstreamer_buffer_free(send); + + exit_stream: + if (priv) + { + if (preroll || !priv->o) return; + + if (!priv->unlocked) + eina_condition_signal(&priv->c); + } +} + +static void +evas_video_sink_main_render(void *data) +{ + Emotion_Gstreamer_Buffer *send; + Emotion_Gstreamer_Video *ev = NULL; + Emotion_Video_Stream *vstream; + EvasVideoSinkPrivate *priv = NULL; + GstBuffer *buffer; + unsigned char *evas_data; + GstFormat fmt = GST_FORMAT_TIME; + gint64 pos; + Eina_Bool preroll = EINA_FALSE; + + send = data; + + if (!send) goto exit_point; + + priv = send->sink; + buffer = send->frame; + preroll = send->preroll; + ev = send->ev; + + /* frame after cleanup */ + if (!preroll && !ev->last_buffer) + { + priv = NULL; + goto exit_point; + } + + if (!priv || !priv->o || priv->unlocked) + goto exit_point; + + if (ev->send && send != ev->send) + { + emotion_gstreamer_buffer_free(ev->send); + ev->send = NULL; + } + + if (!ev->stream && !send->force) + { + ev->send = send; + _emotion_frame_new(ev->obj); + evas_object_image_data_update_add(priv->o, 0, 0, priv->width, priv->height); + goto exit_stream; + } + + _emotion_gstreamer_video_pipeline_parse(ev, EINA_TRUE); + + INF("sink main render [%i, %i] (source height: %i)", priv->width, priv->height, priv->source_height); + + evas_object_image_alpha_set(priv->o, 0); + evas_object_image_colorspace_set(priv->o, priv->eformat); + evas_object_image_size_set(priv->o, priv->width, priv->height); + + evas_data = evas_object_image_data_get(priv->o, 1); + + if (priv->func) + priv->func(evas_data, GST_BUFFER_DATA(buffer), priv->width, priv->source_height, priv->height); + else + WRN("No way to decode %x colorspace !", priv->eformat); + + evas_object_image_data_set(priv->o, evas_data); + evas_object_image_data_update_add(priv->o, 0, 0, priv->width, priv->height); + evas_object_image_pixels_dirty_set(priv->o, 0); + + _update_emotion_fps(ev); + + if (!preroll && ev->play_started) + { + _emotion_playback_started(ev->obj); + ev->play_started = 0; + } + + if (!send->force) + { + _emotion_frame_new(ev->obj); + } + + gst_element_query_position(ev->pipeline, &fmt, &pos); + ev->position = (double)pos / (double)GST_SECOND; + + vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1); + + if (vstream) + { + vstream->width = priv->width; + vstream->height = priv->height; + _emotion_video_pos_update(ev->obj, ev->position, vstream->length_time); + } + + ev->ratio = (double) priv->width / (double) priv->height; + + _emotion_frame_resize(ev->obj, priv->width, priv->height, ev->ratio); + + buffer = gst_buffer_ref(buffer); + if (ev->last_buffer) gst_buffer_unref(ev->last_buffer); + ev->last_buffer = buffer; + + exit_point: + emotion_gstreamer_buffer_free(send); + + exit_stream: + if (priv) + { + if (preroll || !priv->o) return; + + if (!priv->unlocked) + eina_condition_signal(&priv->c); + } +} + +static void +unlock_buffer_mutex(EvasVideoSinkPrivate* priv) +{ + priv->unlocked = EINA_TRUE; + + eina_condition_signal(&priv->c); +} + +static void +marshal_VOID__MINIOBJECT(GClosure * closure, GValue * return_value __UNUSED__, + guint n_param_values, const GValue * param_values, + gpointer invocation_hint __UNUSED__, gpointer marshal_data) +{ + typedef void (*marshalfunc_VOID__MINIOBJECT) (gpointer obj, gpointer arg1, gpointer data2); + marshalfunc_VOID__MINIOBJECT callback; + GCClosure *cc; + gpointer data1, data2; + + cc = (GCClosure *) closure; + + g_return_if_fail(n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA(closure)) { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } else { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + callback = (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : cc->callback); + + callback(data1, gst_value_get_mini_object(param_values + 1), data2); +} + +static void +evas_video_sink_class_init(EvasVideoSinkClass* klass) +{ + GObjectClass* gobject_class; + GstBaseSinkClass* gstbase_sink_class; + + gobject_class = G_OBJECT_CLASS(klass); + gstbase_sink_class = GST_BASE_SINK_CLASS(klass); + + g_type_class_add_private(klass, sizeof(EvasVideoSinkPrivate)); + + gobject_class->set_property = evas_video_sink_set_property; + gobject_class->get_property = evas_video_sink_get_property; + + g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT, + g_param_spec_pointer ("evas-object", "Evas Object", + "The Evas object where the display of the video will be done", + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_WIDTH, + g_param_spec_int ("width", "Width", + "The width of the video", + 0, 65536, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_HEIGHT, + g_param_spec_int ("height", "Height", + "The height of the video", + 0, 65536, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_EV, + g_param_spec_pointer ("ev", "Emotion_Gstreamer_Video", + "THe internal data of the emotion object", + G_PARAM_READWRITE)); + + gobject_class->dispose = evas_video_sink_dispose; + + gstbase_sink_class->set_caps = evas_video_sink_set_caps; + gstbase_sink_class->stop = evas_video_sink_stop; + gstbase_sink_class->start = evas_video_sink_start; + gstbase_sink_class->unlock = evas_video_sink_unlock; + gstbase_sink_class->unlock_stop = evas_video_sink_unlock_stop; + gstbase_sink_class->render = evas_video_sink_render; + gstbase_sink_class->preroll = evas_video_sink_preroll; + + evas_video_sink_signals[REPAINT_REQUESTED] = g_signal_new("repaint-requested", + G_TYPE_FROM_CLASS(klass), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + 0, + 0, + marshal_VOID__MINIOBJECT, + G_TYPE_NONE, 1, GST_TYPE_BUFFER); +} + +gboolean +gstreamer_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, + "emotion-sink", + GST_RANK_NONE, + EVAS_TYPE_VIDEO_SINK); +} + +static void +_emotion_gstreamer_pause(void *data, Ecore_Thread *thread) +{ + Emotion_Gstreamer_Video *ev = data; + gboolean res; + + if (ecore_thread_check(thread) || !ev->pipeline) return ; + + gst_element_set_state(ev->pipeline, GST_STATE_PAUSED); + res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + if (res == GST_STATE_CHANGE_NO_PREROLL) + { + gst_element_set_state(ev->pipeline, GST_STATE_PLAYING); + gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + } +} + +static void +_emotion_gstreamer_cancel(void *data, Ecore_Thread *thread) +{ + Emotion_Gstreamer_Video *ev = data; + + ev->threads = eina_list_remove(ev->threads, thread); + + if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT")); + + if (ev->in == ev->out && ev->delete_me) + em_shutdown(ev); +} + +static void +_emotion_gstreamer_end(void *data, Ecore_Thread *thread) +{ + Emotion_Gstreamer_Video *ev = data; + + ev->threads = eina_list_remove(ev->threads, thread); + + if (ev->play) + { + gst_element_set_state(ev->pipeline, GST_STATE_PLAYING); + ev->play_started = 1; + } + + if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT")); + + if (ev->in == ev->out && ev->delete_me) + em_shutdown(ev); + else + _emotion_gstreamer_video_pipeline_parse(data, EINA_TRUE); +} + +static void +_video_resize(void *data, Evas_Object *obj __UNUSED__, const Evas_Video_Surface *surface __UNUSED__, + Evas_Coord w, Evas_Coord h) +{ +#ifdef HAVE_ECORE_X + Emotion_Gstreamer_Video *ev = data; + + ecore_x_window_resize(ev->win, w, h); + 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; +} diff --git a/src/modules/xine/Makefile.am b/src/modules/xine/Makefile.am index 6ae4990..baf8fec 100644 --- a/src/modules/xine/Makefile.am +++ b/src/modules/xine/Makefile.am @@ -1,4 +1,3 @@ - MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = \ @@ -8,23 +7,25 @@ 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 diff --git a/src/modules/xine/emotion_xine.c b/src/modules/xine/emotion_xine.c index 41624af..dd4a3a5 100644 --- a/src/modules/xine/emotion_xine.c +++ b/src/modules/xine/emotion_xine.c @@ -1,7 +1,17 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + #include "Emotion.h" #include "emotion_private.h" #include "emotion_xine.h" +int _emotion_xine_log_domain = -1; + /* module api */ static unsigned char em_init (Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt); static int em_shutdown (void *ef); @@ -11,13 +21,15 @@ static void em_play (void *ef, double pos); static void em_stop (void *ef); static void em_size_get (void *ef, int *w, int *h); static void em_pos_set (void *ef, double pos); -static 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); @@ -60,10 +72,10 @@ static const char *em_meta_get (void *ef, int meta); /* internal util calls */ static void *_em_slave (void *par); static void _em_slave_event (void *data, int type, void *arg); -static 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); @@ -111,11 +123,11 @@ _em_slave(void *par) 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); @@ -135,31 +147,31 @@ _em_slave(void *par) 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); @@ -182,7 +194,7 @@ _em_slave(void *par) 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)) @@ -214,19 +226,20 @@ _em_slave(void *par) 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; @@ -282,16 +295,12 @@ _em_slave(void *par) 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; @@ -315,12 +324,7 @@ _em_slave(void *par) 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; @@ -363,7 +367,7 @@ _em_slave_event(void *data, int type, void *arg) 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 @@ -403,6 +407,7 @@ em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt) 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; @@ -421,6 +426,8 @@ em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt) 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; @@ -434,18 +441,25 @@ em_shutdown(void *ef) 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; @@ -507,31 +521,27 @@ em_pos_set(void *ef, double pos) 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 @@ -544,11 +554,8 @@ em_fps_num_get(void *ef) } 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; } @@ -567,9 +574,20 @@ em_pos_get(void *ef) Emotion_Xine_Video *ev; ev = (Emotion_Xine_Video *)ef; + _em_get_pos_len(ev); return ev->pos; } +static void +em_vis_set(void *ef, Emotion_Vis vis) +{ + Emotion_Xine_Video *ev; + + ev = (Emotion_Xine_Video *)ef; + if (ev->vis == vis) return; + ev->vis = vis; +} + static Emotion_Vis em_vis_get(void *ef) { @@ -580,6 +598,12 @@ 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) { @@ -667,7 +691,7 @@ em_video_data_size_get(void *ef, int *w, int *h) } static int -em_yuv_rows_get(void *ef, int w, int h, unsigned char **yrows, unsigned char **urows, unsigned char **vrows) +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; @@ -810,7 +834,7 @@ em_event_feed(void *ef, int event) } 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; @@ -885,11 +909,8 @@ em_video_channel_get(void *ef) } 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; } @@ -978,12 +999,13 @@ static void 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 @@ -992,8 +1014,9 @@ em_audio_channel_volume_get(void *ef) 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 @@ -1072,45 +1095,30 @@ em_chapter_count(void *ef) } 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; } @@ -1160,20 +1168,20 @@ em_meta_get(void *ef, int meta) 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) @@ -1192,7 +1200,8 @@ _em_fd_active(void *data, Ecore_Fd_Handler *fdh) } } } - return 1; + return EINA_TRUE; + data = NULL; } static void @@ -1219,7 +1228,7 @@ _em_event(void *data, const xine_event_t *event) } 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 @@ -1236,22 +1245,31 @@ _em_module_event(void *data, int type) 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]; @@ -1265,20 +1283,56 @@ _em_fd_ev_active(void *data, Ecore_Fd_Handler *fdh) 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 */ @@ -1291,8 +1345,20 @@ _em_fd_ev_active(void *data, Ecore_Fd_Handler *fdh) 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; } @@ -1322,29 +1388,18 @@ _em_fd_ev_active(void *data, Ecore_Fd_Handler *fdh) } 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 @@ -1355,15 +1410,16 @@ _em_fd_ev_active(void *data, Ecore_Fd_Handler *fdh) 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; @@ -1391,13 +1447,13 @@ _em_fd_ev_active(void *data, Ecore_Fd_Handler *fdh) 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; } } @@ -1405,7 +1461,7 @@ _em_fd_ev_active(void *data, Ecore_Fd_Handler *fdh) free(eev); } } - return 1; + return EINA_TRUE; } static void * @@ -1442,7 +1498,8 @@ _em_get_pos_len_th(void *par) } } 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) { @@ -1456,7 +1513,7 @@ _em_get_pos_len_th(void *par) 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)); @@ -1473,13 +1530,15 @@ 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 */ @@ -1520,29 +1579,62 @@ static Emotion_Video_Module em_module = 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) @@ -1585,48 +1677,46 @@ 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); } } } diff --git a/src/modules/xine/emotion_xine.h b/src/modules/xine/emotion_xine.h index 8a9efcc..c1cae2e 100644 --- a/src/modules/xine/emotion_xine.h +++ b/src/modules/xine/emotion_xine.h @@ -20,6 +20,9 @@ struct _Emotion_Xine_Video 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; @@ -29,23 +32,22 @@ struct _Emotion_Xine_Video 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; @@ -86,7 +88,11 @@ struct _Emotion_Xine_Event 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 diff --git a/src/modules/xine/emotion_xine_vo_out.c b/src/modules/xine/emotion_xine_vo_out.c index 439ae92..3ae8e1c 100644 --- a/src/modules/xine/emotion_xine_vo_out.c +++ b/src/modules/xine/emotion_xine_vo_out.c @@ -1,11 +1,20 @@ /***************************************************************************/ /*** emotion xine display engine ***/ /***************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include #include +#include +#include +#include + +#include "Emotion.h" #include "emotion_private.h" #include "emotion_xine.h" @@ -60,6 +69,8 @@ struct _Emotion_Lut 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); @@ -111,16 +122,21 @@ plugin_info_t emotion_xine_plugin_info[] = /***************************************************************************/ 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; @@ -138,20 +154,14 @@ _emotion_class_dispose(video_driver_class_t *driver_class) } 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"; } @@ -164,8 +174,8 @@ _emotion_open(video_driver_class_t *driver_class, const void *visual) 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; @@ -186,7 +196,7 @@ _emotion_open(video_driver_class_t *driver_class, const void *visual) 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; } @@ -197,40 +207,31 @@ _emotion_dispose(vo_driver_t *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: @@ -258,13 +259,13 @@ _emotion_property_set(vo_driver_t *vo_driver, int property, int value) 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: @@ -279,7 +280,7 @@ _emotion_property_get(vo_driver_t *vo_driver, int property) Emotion_Driver *dv; dv = (Emotion_Driver *)vo_driver; -// printf("emotion: _emotion_property_get()\n"); +// DBG(""); switch (property) { case VO_PROP_ASPECT_RATIO: @@ -292,26 +293,21 @@ _emotion_property_get(vo_driver_t *vo_driver, int property) } static void -_emotion_property_min_max_get(vo_driver_t *vo_driver, int property, int *min, int *max) +_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; @@ -333,13 +329,13 @@ _emotion_frame_dispose(vo_frame_t *vo_frame) 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; @@ -347,10 +343,10 @@ _emotion_frame_format_update(vo_driver_t *vo_driver, vo_frame_t *vo_frame, uint3 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; @@ -415,12 +411,12 @@ _emotion_frame_format_update(vo_driver_t *vo_driver, vo_frame_t *vo_frame, uint3 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); } @@ -437,15 +433,13 @@ _emotion_frame_display(vo_driver_t *vo_driver, vo_frame_t *vo_frame) 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) @@ -455,11 +449,11 @@ _emotion_frame_display(vo_driver_t *vo_driver, vo_frame_t *vo_frame) 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++; } @@ -468,12 +462,9 @@ _emotion_frame_display(vo_driver_t *vo_driver, vo_frame_t *vo_frame) } static void -_emotion_frame_field(vo_frame_t *vo_frame, int which_field) +_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(""); } /***************************************************************************/ @@ -500,7 +491,7 @@ _emotion_frame_data_free(Emotion_Frame *fr) 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); @@ -510,36 +501,24 @@ _emotion_frame_data_unlock(Emotion_Frame *fr) /***************************************************************************/ 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);